From c8b64523eee5dc58007ae6984575b6a202b2d743 Mon Sep 17 00:00:00 2001 From: Matthew Irish Date: Tue, 26 Jun 2018 16:35:47 -0500 Subject: [PATCH] UI - guard page redesign (#4779) * add NavHeader component * use NavHeader in SplashPage component and application.hbs * let download button take a block * add RadialProgress component * use RadialProgress in ShamirFlow component * style up the RadialProgress component * update ember-basic-dropdown, ember-basic-dropdown-hover * rework operation token generation workflow * directly depend on ember-maybe-in-element --- ui/app/components/download-button.js | 2 +- ui/app/components/hover-copy-button.js | 10 + ui/app/components/i-con.js | 1 + ui/app/components/nav-header.js | 6 + ui/app/components/nav-header/home.js | 5 + ui/app/components/nav-header/items.js | 5 + ui/app/components/nav-header/main.js | 5 + ui/app/components/radial-progress.js | 29 ++ ui/app/components/replication-mode-summary.js | 2 +- ui/app/components/shamir-flow.js | 38 ++- ui/app/components/shamir-progress.js | 5 +- ui/app/components/splash-page.js | 9 + ui/app/components/status-menu.js | 7 +- ui/app/components/upgrade-link.js | 3 + ui/app/helpers/message-types.js | 2 +- .../styles/components/console-ui-panel.scss | 2 +- .../styles/components/hover-copy-button.scss | 24 ++ .../styles/components/init-illustration.scss | 17 +- ui/app/styles/components/message-in-page.scss | 2 +- ui/app/styles/components/popup-menu.scss | 14 +- ui/app/styles/components/radial-progress.scss | 12 + ui/app/styles/components/splash-page.scss | 15 + ui/app/styles/components/sub-nav.scss | 3 +- ui/app/styles/components/unseal-warning.scss | 5 + ui/app/styles/core.scss | 4 + ui/app/styles/core/footer.scss | 1 + ui/app/templates/application.hbs | 130 ++++---- ui/app/templates/components/auth-form.hbs | 10 +- .../components/hover-copy-button.hbs | 17 + ui/app/templates/components/nav-header.hbs | 11 + .../templates/components/nav-header/home.hbs | 1 + .../templates/components/nav-header/items.hbs | 1 + .../templates/components/nav-header/main.hbs | 1 + .../templates/components/radial-progress.hbs | 20 ++ ui/app/templates/components/shamir-flow.hbs | 232 ++++++++------ .../templates/components/shamir-progress.hbs | 4 +- ui/app/templates/components/splash-page.hbs | 29 +- ui/app/templates/components/status-menu.hbs | 4 +- ui/app/templates/components/tool-tip.hbs | 2 + ui/app/templates/components/upgrade-link.hbs | 4 +- .../partials/replication/promote.hbs | 35 +- .../replication-mode-summary-menu.hbs | 10 +- .../partials/replication/update-primary.hbs | 81 +++-- .../templates/partials/status/replication.hbs | 4 +- ui/app/templates/svg/icons/download.hbs | 3 + ui/app/templates/vault/cluster/auth.hbs | 40 +-- ui/app/templates/vault/cluster/init.hbs | 186 +++++------ .../vault/cluster/replication-dr-promote.hbs | 77 +++-- ui/app/templates/vault/cluster/unseal.hbs | 50 ++- ui/app/templates/vault/error.hbs | 16 +- ui/package.json | 5 +- ui/tests/acceptance/unseal-test.js | 5 +- .../components/hover-copy-button-test.js | 39 +++ .../integration/components/nav-header-test.js | 39 +++ .../components/radial-progress-test.js | 33 ++ .../components/shamir-flow-test.js | 29 +- .../components/upgrade-link-test.js | 10 +- .../pages/components/hover-copy-button.js | 9 + ui/tests/pages/components/nav-header.js | 8 + ui/tests/pages/components/radial-progress.js | 13 + ui/tests/test-helper.js | 2 + ui/yarn.lock | 300 ++++++++++++++++-- 62 files changed, 1167 insertions(+), 521 deletions(-) create mode 100644 ui/app/components/hover-copy-button.js create mode 100644 ui/app/components/nav-header.js create mode 100644 ui/app/components/nav-header/home.js create mode 100644 ui/app/components/nav-header/items.js create mode 100644 ui/app/components/nav-header/main.js create mode 100644 ui/app/components/radial-progress.js create mode 100644 ui/app/styles/components/hover-copy-button.scss create mode 100644 ui/app/styles/components/radial-progress.scss create mode 100644 ui/app/styles/components/splash-page.scss create mode 100644 ui/app/styles/components/unseal-warning.scss create mode 100644 ui/app/templates/components/hover-copy-button.hbs create mode 100644 ui/app/templates/components/nav-header.hbs create mode 100644 ui/app/templates/components/nav-header/home.hbs create mode 100644 ui/app/templates/components/nav-header/items.hbs create mode 100644 ui/app/templates/components/nav-header/main.hbs create mode 100644 ui/app/templates/components/radial-progress.hbs create mode 100644 ui/app/templates/svg/icons/download.hbs create mode 100644 ui/tests/integration/components/hover-copy-button-test.js create mode 100644 ui/tests/integration/components/nav-header-test.js create mode 100644 ui/tests/integration/components/radial-progress-test.js create mode 100644 ui/tests/pages/components/hover-copy-button.js create mode 100644 ui/tests/pages/components/nav-header.js create mode 100644 ui/tests/pages/components/radial-progress.js diff --git a/ui/app/components/download-button.js b/ui/app/components/download-button.js index 2e2847c887fa..4ba0c338e12f 100644 --- a/ui/app/components/download-button.js +++ b/ui/app/components/download-button.js @@ -4,7 +4,7 @@ import hbs from 'htmlbars-inline-precompile'; const { computed } = Ember; export default Ember.Component.extend({ - layout: hbs`{{actionText}}`, + layout: hbs`{{#if hasBlock}} {{yield}} {{else}} {{actionText}} {{/if}}`, tagName: 'a', role: 'button', attributeBindings: ['role', 'download', 'href'], diff --git a/ui/app/components/hover-copy-button.js b/ui/app/components/hover-copy-button.js new file mode 100644 index 000000000000..52c59f2f3323 --- /dev/null +++ b/ui/app/components/hover-copy-button.js @@ -0,0 +1,10 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + 'data-test-hover-copy': true, + classNameBindings: 'alwaysShow:hover-copy-button-static:hover-copy-button', + copyValue: null, + alwaysShow: false, + + tooltipText: 'Copy', +}); diff --git a/ui/app/components/i-con.js b/ui/app/components/i-con.js index ff6a10f9dbb2..a4063be406ba 100644 --- a/ui/app/components/i-con.js +++ b/ui/app/components/i-con.js @@ -3,6 +3,7 @@ import hbs from 'htmlbars-inline-precompile'; const { computed } = Ember; const GLYPHS_WITH_SVG_TAG = [ + 'download', 'folder', 'file', 'hidden', diff --git a/ui/app/components/nav-header.js b/ui/app/components/nav-header.js new file mode 100644 index 000000000000..f36a904a1926 --- /dev/null +++ b/ui/app/components/nav-header.js @@ -0,0 +1,6 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + 'data-test-navheader': true, + tagName: 'header', +}); diff --git a/ui/app/components/nav-header/home.js b/ui/app/components/nav-header/home.js new file mode 100644 index 000000000000..e3ac4fb5c0a7 --- /dev/null +++ b/ui/app/components/nav-header/home.js @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + tagName: '', +}); diff --git a/ui/app/components/nav-header/items.js b/ui/app/components/nav-header/items.js new file mode 100644 index 000000000000..e3ac4fb5c0a7 --- /dev/null +++ b/ui/app/components/nav-header/items.js @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + tagName: '', +}); diff --git a/ui/app/components/nav-header/main.js b/ui/app/components/nav-header/main.js new file mode 100644 index 000000000000..e3ac4fb5c0a7 --- /dev/null +++ b/ui/app/components/nav-header/main.js @@ -0,0 +1,5 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + tagName: '', +}); diff --git a/ui/app/components/radial-progress.js b/ui/app/components/radial-progress.js new file mode 100644 index 000000000000..4ad0d8ddb348 --- /dev/null +++ b/ui/app/components/radial-progress.js @@ -0,0 +1,29 @@ +import Ember from 'ember'; +const { computed } = Ember; + +export default Ember.Component.extend({ + 'data-test-radial-progress': true, + tagName: 'svg', + classNames: 'radial-progress', + attributeBindings: ['size:width', 'size:height', 'viewBox'], + progressDecimal: null, + size: 20, + strokeWidth: 1, + + viewBox: computed('size', function() { + let s = this.get('size'); + return `0 0 ${s} ${s}`; + }), + centerValue: computed('size', function() { + return this.get('size') / 2; + }), + r: computed('size', 'strokeWidth', function() { + return (this.get('size') - this.get('strokeWidth')) / 2; + }), + c: computed('r', function() { + return 2 * Math.PI * this.get('r'); + }), + dashArrayOffset: computed('c', 'progressDecimal', function() { + return this.get('c') * (1 - this.get('progressDecimal')); + }), +}); diff --git a/ui/app/components/replication-mode-summary.js b/ui/app/components/replication-mode-summary.js index 6c26d98ec7a8..5035f459adf6 100644 --- a/ui/app/components/replication-mode-summary.js +++ b/ui/app/components/replication-mode-summary.js @@ -34,7 +34,7 @@ export default Ember.Component.extend({ }), isPerformance: computed.equal('mode', 'performance'), replicationEnabled: replicationAttr('replicationEnabled'), - replicationUnsupported: replicationAttr('replicationUnsupported'), + replicationUnsupported: computed.equal('cluster.mode', 'unsupported'), replicationDisabled: replicationAttr('replicationDisabled'), syncProgressPercent: replicationAttr('syncProgressPercent'), syncProgress: replicationAttr('syncProgress'), diff --git a/ui/app/components/shamir-flow.js b/ui/app/components/shamir-flow.js index 5df2bc38d708..585e0942b29f 100644 --- a/ui/app/components/shamir-flow.js +++ b/ui/app/components/shamir-flow.js @@ -9,6 +9,8 @@ const DEFAULTS = { errors: [], threshold: null, progress: null, + pgp_key: null, + haveSavedPGPKey: false, started: false, generateWithPGP: false, pgpKeyFile: { value: '' }, @@ -32,7 +34,7 @@ export default Component.extend(DEFAULTS, { return this._super(...arguments); }, - onShamirSuccess: _ => _, + onShamirSuccess() {}, // can be overridden w/an attr isComplete(data) { return data.complete === true; @@ -76,6 +78,28 @@ export default Component.extend(DEFAULTS, { } }, + generateStep: computed('generateWithPGP', 'haveSavedPGPKey', 'otp', 'pgp_key', function() { + let { generateWithPGP, otp, pgp_key, haveSavedPGPKey } = this.getProperties( + 'generateWithPGP', + 'otp', + 'pgp_key', + 'haveSavedPGPKey' + ); + if (!generateWithPGP && !pgp_key && !otp) { + return 'chooseMethod'; + } + if (otp) { + return 'beginGenerationWithOTP'; + } + if (generateWithPGP) { + if (pgp_key && haveSavedPGPKey) { + return 'beginGenerationWithPGP'; + } else { + return 'providePGPKey'; + } + } + }), + extractData(data) { const isGenerate = this.get('generateAction'); const hasStarted = this.get('started'); @@ -113,6 +137,12 @@ export default Component.extend(DEFAULTS, { }, actions: { + reset() { + this.reset(); + this.set('encoded_token', null); + this.set('otp', null); + }, + onSubmit(data) { if (!data.key) { return; @@ -135,8 +165,10 @@ export default Component.extend(DEFAULTS, { this.set('pgpKeyFile', keyFile); }, - clearToken() { - this.set('encoded_token', null); + savePGPKey() { + if (this.get('pgp_key')) { + this.set('haveSavedPGPKey', true); + } }, }, }); diff --git a/ui/app/components/shamir-progress.js b/ui/app/components/shamir-progress.js index c470cd0a1d3a..bd0fe758d2ec 100644 --- a/ui/app/components/shamir-progress.js +++ b/ui/app/components/shamir-progress.js @@ -1,13 +1,14 @@ import Ember from 'ember'; +const { computed } = Ember; export default Ember.Component.extend({ threshold: null, progress: null, classNames: ['shamir-progress'], - progressPercent: Ember.computed('threshold', 'progress', function() { + progressDecimal: computed('threshold', 'progress', function() { const { threshold, progress } = this.getProperties('threshold', 'progress'); if (threshold && progress) { - return progress / threshold * 100; + return progress / threshold; } return 0; }), diff --git a/ui/app/components/splash-page.js b/ui/app/components/splash-page.js index e3ac4fb5c0a7..708ff64b7d25 100644 --- a/ui/app/components/splash-page.js +++ b/ui/app/components/splash-page.js @@ -1,5 +1,14 @@ import Ember from 'ember'; +const { computed, inject } = Ember; + export default Ember.Component.extend({ + version: inject.service(), + auth: inject.service(), + store: inject.service(), tagName: '', + + activeCluster: computed('auth.activeCluster', function() { + return this.get('store').peekRecord('cluster', this.get('auth.activeCluster')); + }), }); diff --git a/ui/app/components/status-menu.js b/ui/app/components/status-menu.js index 79928a285601..205448a3bb43 100644 --- a/ui/app/components/status-menu.js +++ b/ui/app/components/status-menu.js @@ -7,14 +7,17 @@ export default Ember.Component.extend({ cluster: computed.alias('currentCluster.cluster'), auth: inject.service(), type: 'cluster', + itemTag: null, partialName: computed('type', function() { - return `partials/status/${this.get('type')}`; + let type = this.get('type'); + let partial = type === 'replication-status' ? 'replication' : type; + return `partials/status/${partial}`; }), glyphName: computed('type', function() { const glyphs = { cluster: 'unlocked', user: 'android-person', - replication: 'replication', + 'replication-status': 'replication', }; return glyphs[this.get('type')]; }), diff --git a/ui/app/components/upgrade-link.js b/ui/app/components/upgrade-link.js index 01bc9ea11d79..f02f5a79f344 100644 --- a/ui/app/components/upgrade-link.js +++ b/ui/app/components/upgrade-link.js @@ -3,6 +3,9 @@ import Ember from 'ember'; const { computed } = Ember; export default Ember.Component.extend({ + modalContainer: computed(function() { + return document.getElementById('modal-wormhole'); + }), isAnimated: false, isActive: false, tagName: 'span', diff --git a/ui/app/helpers/message-types.js b/ui/app/helpers/message-types.js index a42e8f2f1931..ea01ef1bbb3c 100644 --- a/ui/app/helpers/message-types.js +++ b/ui/app/helpers/message-types.js @@ -23,7 +23,7 @@ const MESSAGE_TYPES = { class: 'is-highlight', glyphClass: 'has-text-highlight', glyph: 'alert-circled', - text: 'Attention', + text: 'Warning', }, }; diff --git a/ui/app/styles/components/console-ui-panel.scss b/ui/app/styles/components/console-ui-panel.scss index 7507762e8402..ecc558015a51 100644 --- a/ui/app/styles/components/console-ui-panel.scss +++ b/ui/app/styles/components/console-ui-panel.scss @@ -142,7 +142,7 @@ } } -.page-container > header { +.page-container > header:not(.page-header) { background: linear-gradient(to right, #191a1c, #1b212d); } diff --git a/ui/app/styles/components/hover-copy-button.scss b/ui/app/styles/components/hover-copy-button.scss new file mode 100644 index 000000000000..5d62d334b919 --- /dev/null +++ b/ui/app/styles/components/hover-copy-button.scss @@ -0,0 +1,24 @@ +.has-copy-button { + position: relative; + color: $grey; +} +.hover-copy-button, +.hover-copy-button-static { + position: absolute; + top: 0.5rem; + right: 0.5rem; +} + +.hover-copy-button { + opacity: 0; + pointer-events: none; + transition: opacity $speed ease-in-out; + will-change: opacity; +} + +.has-copy-button:hover .hover-copy-button, +.has-copy-button:focus .hover-copy-button, +.hover-copy-button .copy-button:focus { + opacity: 1; + pointer-events: auto; +} diff --git a/ui/app/styles/components/init-illustration.scss b/ui/app/styles/components/init-illustration.scss index 5cc72e28e926..1f18018b8c1d 100644 --- a/ui/app/styles/components/init-illustration.scss +++ b/ui/app/styles/components/init-illustration.scss @@ -1,5 +1,18 @@ +.init-box { + position: relative; + z-index: 10; +} .init-illustration { + bottom: 0; + right: 0; + overflow: hidden; + position: absolute; + height: 200px; + width: 200px; +} +.init-illustration svg { position: absolute; - left: calc(50% - 100px); - top: -94px; + right: -50px; + bottom: -50px; + opacity: 0.8; } diff --git a/ui/app/styles/components/message-in-page.scss b/ui/app/styles/components/message-in-page.scss index 936e2273e190..e766d8826fdf 100644 --- a/ui/app/styles/components/message-in-page.scss +++ b/ui/app/styles/components/message-in-page.scss @@ -1,5 +1,5 @@ .message-in-page { - margin-bottom: 2rem; + margin-bottom: 1rem; position: relative; .close-button { diff --git a/ui/app/styles/components/popup-menu.scss b/ui/app/styles/components/popup-menu.scss index 3594d830f930..928b94b148b1 100644 --- a/ui/app/styles/components/popup-menu.scss +++ b/ui/app/styles/components/popup-menu.scss @@ -28,7 +28,6 @@ background: transparent; box-shadow: none; border: none; - color: $menu-item-color; display: block; height: auto; font-size: $size-7; @@ -37,7 +36,11 @@ text-align: left; text-decoration: none; width: 100%; + } + button.link, + a { + color: $menu-item-color; &:hover { background-color: $menu-item-hover-background-color; color: $menu-item-hover-color; @@ -79,6 +82,15 @@ } } +.popup-menu-content p { + box-shadow: none; + padding-top: $size-10; + font-weight: $font-weight-semibold; +} + +.popup-menu-content .level-left { + flex-shrink: 1; +} .popup-menu-trigger { height: 2rem; min-width: 0; diff --git a/ui/app/styles/components/radial-progress.scss b/ui/app/styles/components/radial-progress.scss new file mode 100644 index 000000000000..4f17bd6cd215 --- /dev/null +++ b/ui/app/styles/components/radial-progress.scss @@ -0,0 +1,12 @@ +.radial-progress { + transform: rotate(-90deg) translateX(-20%); +} +.radial-progress circle { + stroke: rgba($grey-light, 0.5); + transition: stroke-dashoffset $speed ease-in; + will-change: stroke-dashoffset; + stroke-linecap: round; +} +.radial-progress circle.progress-fill { + stroke: $green; +} diff --git a/ui/app/styles/components/splash-page.scss b/ui/app/styles/components/splash-page.scss new file mode 100644 index 000000000000..a361a6a41a76 --- /dev/null +++ b/ui/app/styles/components/splash-page.scss @@ -0,0 +1,15 @@ +a.splash-page-logo { + color: $white; + svg { + transform: scale(.5); + transform-origin: left; + fill: currentColor; + } +} + +.splash-page-container { + margin: $size-2 0; +} +.splash-page-header { + padding: .75rem 1.5rem; +} diff --git a/ui/app/styles/components/sub-nav.scss b/ui/app/styles/components/sub-nav.scss index 630ac3398ef9..3be16a876a13 100644 --- a/ui/app/styles/components/sub-nav.scss +++ b/ui/app/styles/components/sub-nav.scss @@ -23,8 +23,7 @@ color: $grey-dark; font-weight: $font-weight-semibold; text-decoration: none; - padding: $size-6 0; - margin: 0 $size-4; + padding: $size-6 $size-8 $size-8; border-bottom: 2px solid transparent; transition: border-color $speed; diff --git a/ui/app/styles/components/unseal-warning.scss b/ui/app/styles/components/unseal-warning.scss new file mode 100644 index 000000000000..817a67a372c9 --- /dev/null +++ b/ui/app/styles/components/unseal-warning.scss @@ -0,0 +1,5 @@ +.unseal-warning.message, +.unseal-warning .message-body { + border-radius: 0; + margin-bottom: 0; +} diff --git a/ui/app/styles/core.scss b/ui/app/styles/core.scss index dabbb6525709..0caed8431ab8 100644 --- a/ui/app/styles/core.scss +++ b/ui/app/styles/core.scss @@ -50,6 +50,7 @@ @import "./components/env-banner"; @import "./components/form-section"; @import "./components/global-flash"; +@import "./components/hover-copy-button"; @import "./components/init-illustration"; @import "./components/info-table-row"; @import "./components/input-hint"; @@ -61,12 +62,15 @@ @import "./components/message-in-page"; @import "./components/page-header"; @import "./components/popup-menu"; +@import "./components/radial-progress"; @import "./components/role-item"; @import "./components/shamir-progress"; @import "./components/sidebar"; +@import "./components/splash-page"; @import "./components/status-menu"; @import "./components/sub-nav"; @import "./components/token-expire-warning"; @import "./components/tool-tip"; +@import "./components/unseal-warning"; @import "./components/upgrade-overlay"; @import "./components/vault-loading"; diff --git a/ui/app/styles/core/footer.scss b/ui/app/styles/core/footer.scss index b176a8366630..fc3b45182738 100644 --- a/ui/app/styles/core/footer.scss +++ b/ui/app/styles/core/footer.scss @@ -1,6 +1,7 @@ .footer { border-top: $base-border; padding: $size-3 1.5rem; + margin-top: auto; span:not(:first-child) { display: inline-block; diff --git a/ui/app/templates/application.hbs b/ui/app/templates/application.hbs index 9a0e3abd207a..b00dafb52c97 100644 --- a/ui/app/templates/application.hbs +++ b/ui/app/templates/application.hbs @@ -1,73 +1,73 @@
{{#if showNav}} -
- -
+ + + {{console/ui-panel isFullscreen=consoleFullscreen}} + + {{/if}}
{{#each flashMessages.queue as |flash|}} diff --git a/ui/app/templates/components/auth-form.hbs b/ui/app/templates/components/auth-form.hbs index 2d94e536adfd..d594a77d009b 100644 --- a/ui/app/templates/components/auth-form.hbs +++ b/ui/app/templates/components/auth-form.hbs @@ -20,8 +20,8 @@ {{message-error errorMessage=error data-test-auth-error=true}} {{/if}} {{partial providerPartialName}} -
- {{#unless (eq selectedAuthBackend.type "token")}} + {{#unless (eq selectedAuthBackend.type "token")}} +
{{toggle-button toggleTarget=this toggleAttr="useCustomPath"}}
{{#if useCustomPath}} @@ -43,10 +43,10 @@

{{/if}}
- {{/unless}} -
+
+ {{/unless}}
-
+
diff --git a/ui/app/templates/components/hover-copy-button.hbs b/ui/app/templates/components/hover-copy-button.hbs new file mode 100644 index 000000000000..7a35dc92fa35 --- /dev/null +++ b/ui/app/templates/components/hover-copy-button.hbs @@ -0,0 +1,17 @@ + + + + + + +
+ {{tooltipText}} +
+
+
diff --git a/ui/app/templates/components/nav-header.hbs b/ui/app/templates/components/nav-header.hbs new file mode 100644 index 000000000000..73fd0b1c5982 --- /dev/null +++ b/ui/app/templates/components/nav-header.hbs @@ -0,0 +1,11 @@ + +
+ {{yield (hash main=(component 'nav-header/main'))}} +
diff --git a/ui/app/templates/components/nav-header/home.hbs b/ui/app/templates/components/nav-header/home.hbs new file mode 100644 index 000000000000..889d9eeadc10 --- /dev/null +++ b/ui/app/templates/components/nav-header/home.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/ui/app/templates/components/nav-header/items.hbs b/ui/app/templates/components/nav-header/items.hbs new file mode 100644 index 000000000000..889d9eeadc10 --- /dev/null +++ b/ui/app/templates/components/nav-header/items.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/ui/app/templates/components/nav-header/main.hbs b/ui/app/templates/components/nav-header/main.hbs new file mode 100644 index 000000000000..889d9eeadc10 --- /dev/null +++ b/ui/app/templates/components/nav-header/main.hbs @@ -0,0 +1 @@ +{{yield}} diff --git a/ui/app/templates/components/radial-progress.hbs b/ui/app/templates/components/radial-progress.hbs new file mode 100644 index 000000000000..775a9ac65f9a --- /dev/null +++ b/ui/app/templates/components/radial-progress.hbs @@ -0,0 +1,20 @@ + + diff --git a/ui/app/templates/components/shamir-flow.hbs b/ui/app/templates/components/shamir-flow.hbs index 79b9d45de6e5..d1cf0518a968 100644 --- a/ui/app/templates/components/shamir-flow.hbs +++ b/ui/app/templates/components/shamir-flow.hbs @@ -1,139 +1,173 @@ {{#if encoded_token}}
-
+
+
-

+

Encoded Operation Token

{{encoded_token}}
-

+

If you entered a One Time Password, you can use the Vault CLI to decode the Token:

-
-
-

- DR Operation Token Command -

- - vault operator generate-root -otp="[enter your otp here]" -decode="{{encoded_token}}" - -
+
+ {{#with (if otp + (concat 'vault operator generate-root -otp="' otp '" -decode="' encoded_token '"') + (concat 'vault operator generate-root -otp="" -decode="' encoded_token '"') + ) as |cmd|}} + +
+

+ DR Operation Token Command +

+ {{cmd}} +
+ {{/with}}
- {{#copy-button - clipboardText=(concat 'vault operator generate-root -otp="" -decode="' encoded_token '"') - class="button is-compact" - buttonType="button" - success=(action (set-flash-message 'CLI command copied!')) - }} - Copy CLI command - {{/copy-button}}
-
- {{#copy-button - clipboardText=encoded_token - class="button is-primary" - buttonType="button" - success=(action (set-flash-message 'OTP copied!')) - }} - Copy Encoded Operation Token - {{/copy-button}} -
{{else if (and generateAction (not started))}}
-
{{message-error errors=errors}} -

- Updating or promoting this cluster requires an operation token. Let's generate one by - inputting the master key shares. To get started you'll need to generate a One Time Password - (OTP) or a PGP Key to encrypt the resultant operation token. -

-
-
-
-
- {{input type="checkbox" - id="generateWithPGP" - class="styled" - checked=generateWithPGP - }} - -
+ {{#if (eq generateStep 'chooseMethod')}} +
+

+ Updating or promoting this cluster requires an operation token. Let's generate one by + inputting the master key shares. To get started you'll need to generate a One Time Password + (OTP) or provide a PGP Key to encrypt the resultant operation token. +

+
+
+
+ +
+
+ + or + +
+
+
- {{#unless generateWithPGP}} -
-
- -
-
- {{/unless}}
-
- {{#if generateWithPGP}} + {{/if}} + + {{#if (eq generateStep 'providePGPKey')}} + +
+

+ Choose a PGP Key from your computer or paste the contents of one in the form below. + This key will be used to Encrypt the generated Operation Token. +

{{pgp-file index='' key=pgpKeyFile onChange=(action 'setKey')}} - {{else}} - {{#if otp}} -
+
+ +
+
+ +
+
+ +
+
+ {{/if}} + {{#if (eq generateStep 'beginGenerationWithPGP')}} +
+

+ Below is the base-64 encoded PGP Key that will be used to encrypt the generated Operation Token. + Next we'll enter portions of the master key to generate an Operation Token. Click the "Generate Operation Token" button to proceed. +

+
+ +
+

+ PGP Key {{pgpKeyFile.fileName}} +

+ {{pgp_key}} +
+
+
+
+
+ +
+
+ +
+
+ {{/if}} + {{#if (eq generateStep 'beginGenerationWithOTP')}} +
+

+ Below is the generated OTP. This will be used to encrypt the generated Operation Token. + + Make sure to save this, as you will need it later to decrypt the Operation Token. + + Next we'll enter portions of the master key to generate an Operation Token. Click the "Generate Operation Token" button to proceed. +

+
+
-

+

One Time Password

{{otp}}
- {{/if}} -
- {{#if otp}} -
- {{#copy-button - clipboardText=otp - class="button is-compact" - buttonType="button" - success=(action (set-flash-message 'OTP copied!')) - }} - Copy OTP - {{/copy-button}} -
-

Make sure to save this value for later.

- {{/if}} +
+
+
+ +
+
+ +
{{/if}} -
-
- -
{{else}}
-
+
{{message-error errors=errors}} -
- {{#if hasBlock}} - {{yield}} - {{else}} -

{{formText}}

- {{/if}} -
+ {{#if hasBlock}} + {{yield}} + {{else}} +

{{formText}}

+ {{/if}} +
+
{{input class="input"type="password" name="key" value=key data-test-shamir-input=true}}
-
+
diff --git a/ui/app/templates/components/shamir-progress.hbs b/ui/app/templates/components/shamir-progress.hbs index 053c283cf98a..eb905fda8dc2 100644 --- a/ui/app/templates/components/shamir-progress.hbs +++ b/ui/app/templates/components/shamir-progress.hbs @@ -1,10 +1,10 @@
- {{progress}} / {{threshold}} keys provided + {{progress}}/{{threshold}} keys provided
- +
diff --git a/ui/app/templates/components/splash-page.hbs b/ui/app/templates/components/splash-page.hbs index 7b0a2bf9ca8f..0533ce9ee3a2 100644 --- a/ui/app/templates/components/splash-page.hbs +++ b/ui/app/templates/components/splash-page.hbs @@ -1,15 +1,24 @@ -
+ + + + {{partial "svg/vault-edition-logo"}} + + + + {{#if (and activeCluster.unsealed version.isEnterprise)}} + + {{/if}} + + +
-
+
+
+ {{yield (hash header=(component 'splash-page/splash-header'))}} +
{{yield (hash footer=(component 'splash-page/splash-content')) }} diff --git a/ui/app/templates/components/status-menu.hbs b/ui/app/templates/components/status-menu.hbs index 50a16e37758d..435951c3310b 100644 --- a/ui/app/templates/components/status-menu.hbs +++ b/ui/app/templates/components/status-menu.hbs @@ -5,7 +5,7 @@ {{i-con glyph=glyphName class="has-text-dark-grey auto-width" - size=16 + size=18 aria-label=ariaLabel }}
@@ -19,7 +19,7 @@ {{i-con glyph=glyphName class="has-text-white auto-width" - size=16 + size=20 aria-label=ariaLabel }} {{i-con glyph="chevron-down" aria-hidden="true" size=8 class="has-text-white auto-width is-status-chevron"}} diff --git a/ui/app/templates/components/tool-tip.hbs b/ui/app/templates/components/tool-tip.hbs index 4526b64242de..b8f5832c617c 100644 --- a/ui/app/templates/components/tool-tip.hbs +++ b/ui/app/templates/components/tool-tip.hbs @@ -1,4 +1,6 @@ {{#basic-dropdown-hover + onOpen=onOpen + onClose=onClose renderInPlace=renderInPlace verticalPosition=verticalPosition horizontalPosition=horizontalPosition diff --git a/ui/app/templates/components/upgrade-link.hbs b/ui/app/templates/components/upgrade-link.hbs index 611a67d373a0..3be720162e28 100644 --- a/ui/app/templates/components/upgrade-link.hbs +++ b/ui/app/templates/components/upgrade-link.hbs @@ -2,6 +2,6 @@ {{yield}} -{{#ember-wormhole to="modal-wormhole"}} +{{#maybe-in-element modalContainer false}} {{partial "partials/upgrade-overlay"}} -{{/ember-wormhole}} +{{/maybe-in-element}} diff --git a/ui/app/templates/partials/replication/promote.hbs b/ui/app/templates/partials/replication/promote.hbs index 9d0927f33ec3..24d7347b9cf8 100644 --- a/ui/app/templates/partials/replication/promote.hbs +++ b/ui/app/templates/partials/replication/promote.hbs @@ -1,6 +1,6 @@ {{#if (and (eq replicationMode 'dr') (eq model.replicationAttrs.modeForUrl 'secondary'))}}
-

+

This cluster is currently running as a DR Replication Secondary. Promote the cluster to a primary by entering DR Operation Token.

@@ -12,19 +12,30 @@ {{input class="input" id="dr_operation_token" name="dr_operation_token" value=dr_operation_token}}
-
- -
- {{input class="input" id="primary_cluster_addr" name="primary_cluster_addr" value=primary_cluster_addr}} + + {{#if showOptions}} +
+
+ +
+ {{input class="input" id="primary_cluster_addr" name="primary_cluster_addr" value=primary_cluster_addr}} +
+

+ Overrides the cluster address that the primary gives to secondary nodes. +

+
-

- Overrides the cluster address that the primary gives to secondary nodes. -

-
+ {{/if}}
-
+
{{#confirm-action diff --git a/ui/app/templates/partials/replication/replication-mode-summary-menu.hbs b/ui/app/templates/partials/replication/replication-mode-summary-menu.hbs index efb24a35ca1b..7350399649de 100644 --- a/ui/app/templates/partials/replication/replication-mode-summary-menu.hbs +++ b/ui/app/templates/partials/replication/replication-mode-summary-menu.hbs @@ -1,7 +1,9 @@
- {{#if (or replicationUnsupported (and (eq mode 'performance') (not version.hasPerfReplication)))}} + {{#if replicationUnsupported}} + Unsupported + {{else if (and (eq mode 'performance') (not version.hasPerfReplication))}}

Upgrade to Vault Enterprise Premium to use Performance Replication.

@@ -22,7 +24,11 @@ {{else}} - Enable + {{#if (eq tagName 'a')}} + Enable + {{else}} + Disabled + {{/if}} {{/if}}
diff --git a/ui/app/templates/partials/replication/update-primary.hbs b/ui/app/templates/partials/replication/update-primary.hbs index bfc372d82cef..7db07b47de69 100644 --- a/ui/app/templates/partials/replication/update-primary.hbs +++ b/ui/app/templates/partials/replication/update-primary.hbs @@ -1,6 +1,6 @@ {{#if (and (eq replicationMode 'dr') (eq model.replicationAttrs.modeForUrl 'secondary'))}}
-

+

Change a secondary cluster’s assigned primary cluster using a secondary activation token. This does not wipe all data in the cluster.

@@ -20,43 +20,54 @@ {{textarea value=token id="secondary-token" name="secondary-token" class="textarea"}}
-
- -
- {{input class="input" value=primary_api_addr id="primary_api_addr" name="primary_api_addr"}} -
-

- Set this to the API address (normal Vault address) to override the - value embedded in the token. -

-
-
- -
- {{input value=ca_file id="ca_file" name="ca_file" class="input"}} -
-

- Specifies the path to a CA root file (PEM format) that the secondary can use when unwrapping the token from the primary. -

-
-
- -
- {{input value=ca_path id="ca_path" name="ca_file" class="input"}} + + {{#if showOptions}} +
+
+ +
+ {{input class="input" value=primary_api_addr id="primary_api_addr" name="primary_api_addr"}} +
+

+ Set this to the API address (normal Vault address) to override the + value embedded in the token. +

+
+
+ +
+ {{input value=ca_file id="ca_file" name="ca_file" class="input"}} +
+

+ Specifies the path to a CA root file (PEM format) that the secondary can use when unwrapping the token from the primary. +

+
+
+ +
+ {{input value=ca_path id="ca_path" name="ca_file" class="input"}} +
+

+ Specifies the path to a CA root directory containing PEM-format files that the secondary can use when unwrapping the token from the primary. +

+
-

- Specifies the path to a CA root directory containing PEM-format files that the secondary can use when unwrapping the token from the primary. -

-
+ {{/if}}
-
+
{{#confirm-action diff --git a/ui/app/templates/partials/status/replication.hbs b/ui/app/templates/partials/status/replication.hbs index 5aaeccacd6b0..dfb34b8e2b14 100644 --- a/ui/app/templates/partials/status/replication.hbs +++ b/ui/app/templates/partials/status/replication.hbs @@ -8,7 +8,7 @@ mode="dr" display='menu' cluster=cluster - tagName='a' + tagName=(or itemTag 'a') click=(action d.actions.close) }} @@ -21,7 +21,7 @@ mode="performance" display='menu' cluster=cluster - tagName='a' + tagName=(or itemTag 'a') click=(action d.actions.close) }} diff --git a/ui/app/templates/svg/icons/download.hbs b/ui/app/templates/svg/icons/download.hbs new file mode 100644 index 000000000000..5d56bd0ddd4d --- /dev/null +++ b/ui/app/templates/svg/icons/download.hbs @@ -0,0 +1,3 @@ + + + diff --git a/ui/app/templates/vault/cluster/auth.hbs b/ui/app/templates/vault/cluster/auth.hbs index 78aab10dd05d..292850f34b9a 100644 --- a/ui/app/templates/vault/cluster/auth.hbs +++ b/ui/app/templates/vault/cluster/auth.hbs @@ -1,30 +1,22 @@ -{{#splash-page as |s|}} - {{#s.header}} -
+{{!-- {{i-con glyph="unlocked" size=20}} {{capitalize model.name}} is {{if model.unsealed 'unsealed' 'sealed'}} --}} + + +

Sign in to Vault -

- {{/s.header}} - {{#s.content}} -
-
-
-
- {{i-con glyph="unlocked" size=20}} {{capitalize model.name}} is {{if model.unsealed 'unsealed' 'sealed'}} -
-
-
-
- {{auth-form - cluster=model - redirectTo=redirectTo - selectedAuthType=with - }} - {{/s.content}} - {{#s.footer}} + + + + + +

Contact your administrator for login credentials

- {{/s.footer}} -{{/splash-page}} +
+ diff --git a/ui/app/templates/vault/cluster/init.hbs b/ui/app/templates/vault/cluster/init.hbs index db068bfa2261..b3be6a9a07e9 100644 --- a/ui/app/templates/vault/cluster/init.hbs +++ b/ui/app/templates/vault/cluster/init.hbs @@ -1,42 +1,36 @@ -{{#splash-page as |s|}} - {{#s.header}} -
- Connect to Vault and initialize -
- {{/s.header}} - {{#s.content}} - {{#if keyData}} + + {{#if keyData}} + +

+ Vault has been initialized! {{#if (eq keyData.keys.length 1)}} + Here is your key. + {{else}} + Here are your {{pluralize keyData.keys.length "key"}}. + {{/if}} +

+
+
-
-
-

- Vault has been initialized! -

-
-
-
- {{partial "svg/initialize"}} -
-
+
+

+ Please securely distribute the keys below. When the Vault is re-sealed, restarted, or stopped, you must provide at least {{secret_threshold}} of these keys to unseal it again. + Vault does not store the master key. Without at least {{secret_threshold}} keys, your Vault will remain permanently sealed. +

-
+
+
-

+

Initial Root Token

{{keyData.root_token}}
-
-

- Please securely distribute the keys below. When the Vault is re-sealed, restarted, or stopped, you must provide at least {{secret_threshold}} of these keys to unseal it again. - Vault does not store the master key. Without at least {{secret_threshold}} keys, your Vault will remain permanently sealed. -

-
{{#each (if keyData.keys_base64 keyData.keys_base64 keyData.keys) as |key index| }} -
+
+
-

+

Key {{add index 1}}

{{key}} @@ -44,7 +38,7 @@
{{/each}}
-
+
{{#if model.sealed}}
@@ -59,18 +53,26 @@ {{/link-to}}
{{/if}} - {{download-button - actionText="Download Keys" - data=keyData - filename=keyFilename - mime="application/json" - extension="json" - class="button" - stringify=true - }} + + Download Keys +
- {{else}} + + {{else}} + +

+ Let's set up the initial set of master keys that you’ll need in case of an emergency +

+
+
-
-
-

- Let’s set up the initial set of master keys and the backend data store structure -

-
-
-
- {{partial "svg/initialize"}} -
+ +
+ +
+ {{input class="input" autocomplete="off" name="key-shares" type="number" step="1" min="1" pattern="[0-9]*" value=secret_shares}}
+

+ The number of key shares to split the master key into +

- {{message-error errors=errors}} -
-
-
- -
- {{input class="input" name="key-shares" type="number" step="1" min="1" pattern="[0-9]*" value=secret_shares}} -
-

- The number of key shares to split the master key into -

-
-
-
-
- -
- {{input class="input" name="key-threshold" type="number" step="1" min="1" pattern="[0-9]*" value=secret_threshold}} -
-

- The number of key shares required to reconstruct the master key -

-
+
+ +
+ {{input class="input" autocomplete="off" name="key-threshold" type="number" step="1" min="1" pattern="[0-9]*" value=secret_threshold}}
+

+ The number of key shares required to reconstruct the master key +

- {{toggle-button - openLabel="Encrypt Output with PGP" - closedLabel="Encrypt Output with PGP" - toggleTarget=this - toggleAttr="use_pgp" - class="is-block" - }} + {{#if use_pgp}} -
+

The output unseal keys will be encrypted and hex-encoded, in order, with the given public keys.

- {{pgp-list listLength=secret_shares onDataUpdate=(action 'setKeys')}} +
{{/if}} - {{toggle-button - openLabel="Encrypt Root Token with PGP" - closedLabel="Encrypt Root Token with PGP" - toggleTarget=this - toggleAttr="use_pgp_for_root" - class="is-block" - }} + {{#if use_pgp_for_root}} -
+

The root unseal key will be encrypted and hex-encoded with the given public key.

- {{pgp-list listLength=1 onDataUpdate=(action 'setRootKey')}} +
{{/if}}
-
+
+ +
+ {{partial "svg/initialize"}} +
- {{/if}} - {{/s.content}} -{{/splash-page}} + + {{/if}} + diff --git a/ui/app/templates/vault/cluster/replication-dr-promote.hbs b/ui/app/templates/vault/cluster/replication-dr-promote.hbs index e5e7463f7299..a2fc06535c21 100644 --- a/ui/app/templates/vault/cluster/replication-dr-promote.hbs +++ b/ui/app/templates/vault/cluster/replication-dr-promote.hbs @@ -1,15 +1,20 @@ -{{#splash-page as |s|}} - {{#s.header}} -
- Disaster Recovery Secondary is enabled -
- {{/s.header}} - {{#s.content}} + + +

+ Disaster Recovery Secondary is enabled +

+
+ {{#if (eq action 'promote')}} -
-
-
-
- {{i-con glyph="alert-circled" size=28 excludeIconClass=true}} -
-
-

- - Caution: Vault replication is not designed for active-active usage and enabling two performance primaries should never be done, as it can lead to data loss if they or their secondaries are ever reconnected. - -

-
-
-
-
- {{replication-actions replicationMode="dr" selectedAction="promote" model=model}} + + Caution: Vault replication is not designed for active-active usage and enabling two performance primaries should never be done, as it can lead to data loss if they or their secondaries are ever reconnected. + + {{/if}} {{#if (eq action 'update')}} - {{replication-actions replicationMode="dr" selectedAction="updatePrimary" model=model}} + {{/if}} {{#unless action}} - {{#shamir-flow - action="generate-dr-operation-token" - buttonText="Promote cluster" - fetchOnInit=true - generateAction=true - }} -

+ +

Generate an Operation Token by entering a portion of the master key. Once all portions are entered, the generated operation token may be used to manage your Seondary Disaster Recovery cluster.

- {{/shamir-flow}} + {{/unless}} - {{/s.content}} -{{/splash-page}} +
+
diff --git a/ui/app/templates/vault/cluster/unseal.hbs b/ui/app/templates/vault/cluster/unseal.hbs index 73c7ab8e8ac4..422d0641d785 100644 --- a/ui/app/templates/vault/cluster/unseal.hbs +++ b/ui/app/templates/vault/cluster/unseal.hbs @@ -1,31 +1,25 @@ -{{#splash-page as |s|}} - {{#s.header}} -
+ + +

Unseal Vault -

- {{/s.header}} - {{#s.content}} -
-
-
-
- {{i-con glyph="unlocked" size=20}} {{capitalize model.name}} is {{if model.unsealed 'unsealed' 'sealed'}} -
-
-
-
- {{#shamir-flow - action="unseal" - onShamirSuccess=(action 'transitionToCluster') - buttonText="Unseal" - thresholdPath="t" - isComplete=(action 'isUnsealed') - threshold=model.sealThreshold - progress=model.sealProgress - }} -

+ + + + + {{capitalize model.name}} is {{if model.unsealed 'unsealed' 'sealed'}} + + +

Unseal the vault by entering a portion of the master key. Once all portions are entered, the vault will be unsealed.

- {{/shamir-flow}} - {{/s.content}} -{{/splash-page}} + + + diff --git a/ui/app/templates/vault/error.hbs b/ui/app/templates/vault/error.hbs index 1fa6e5188bd9..ec43dfa41714 100644 --- a/ui/app/templates/vault/error.hbs +++ b/ui/app/templates/vault/error.hbs @@ -1,12 +1,10 @@ -
- -
+ + + + {{partial "svg/vault-edition-logo"}} + + +
{{#if (eq model.httpStatus 404)}} diff --git a/ui/package.json b/ui/package.json index ee6fc798ce03..ca5a00441986 100644 --- a/ui/package.json +++ b/ui/package.json @@ -47,8 +47,8 @@ "ember-ajax": "^3.0.0", "ember-angle-bracket-invocation-polyfill": "^1.0.2", "ember-api-actions": "^0.1.8", - "ember-basic-dropdown": "^0.33.5", - "ember-basic-dropdown-hover": "^0.2.0", + "ember-basic-dropdown": "^1.0.0", + "ember-basic-dropdown-hover": "^0.5.0", "ember-cli": "~2.16.0", "ember-cli-autoprefixer": "^0.8.1", "ember-cli-babel": "^6.3.0", @@ -81,6 +81,7 @@ "ember-fetch": "^3.4.3", "ember-href-to": "^1.13.0", "ember-load-initializers": "^1.0.0", + "ember-maybe-in-element": "^0.1.3", "ember-moment": "7.0.0-beta.5", "ember-qunit-assert-helpers": "^0.1.3", "ember-radio-button": "^1.1.1", diff --git a/ui/tests/acceptance/unseal-test.js b/ui/tests/acceptance/unseal-test.js index d5a3c0600c8f..b009764d4f32 100644 --- a/ui/tests/acceptance/unseal-test.js +++ b/ui/tests/acceptance/unseal-test.js @@ -36,10 +36,7 @@ test('seal then unseal', function(assert) { pollCluster(); }); andThen(() => { - assert.ok( - find('[data-test-cluster-status]').text().includes('is unsealed'), - 'ui indicates the vault is unsealed' - ); + assert.equal(find('[data-test-cluster-status]').length, 0, 'ui does not show sealed warning'); assert.ok(currentURL().match(/\/vault\/auth/), 'vault is ready to authenticate'); }); }); diff --git a/ui/tests/integration/components/hover-copy-button-test.js b/ui/tests/integration/components/hover-copy-button-test.js new file mode 100644 index 000000000000..9f114a255d47 --- /dev/null +++ b/ui/tests/integration/components/hover-copy-button-test.js @@ -0,0 +1,39 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import { create } from 'ember-cli-page-object'; +import hbs from 'htmlbars-inline-precompile'; +import copyButton from 'vault/tests/pages/components/hover-copy-button'; +import { triggerSuccess } from '../../helpers/ember-cli-clipboard'; +const component = create(copyButton); + +moduleForComponent('hover-copy-button', 'Integration | Component | hover copy button', { + integration: true, + + beforeEach() { + component.setContext(this); + }, + + afterEach() { + component.removeContext(); + }, +}); + +test('it shows success message in tooltip', function(assert) { + this.set('copyValue', 'foo'); + this.render( + hbs`
{{hover-copy-button copyValue=copyValue}}
` + ); + + component.focusContainer(); + assert.ok(component.buttonIsVisible); + component.mouseEnter(); + assert.equal(component.tooltipText, 'Copy', 'shows copy'); + triggerSuccess(this, '[data-test-hover-copy-button]'); + assert.equal(component.tooltipText, 'Copied!', 'shows success message'); +}); + +test('it has the correct class when alwaysShow is true', function(assert) { + this.set('copyValue', 'foo'); + this.render(hbs`{{hover-copy-button alwaysShow=true copyValue=copyValue}}`); + assert.ok(component.buttonIsVisible); + assert.ok(component.wrapperClass.includes('hover-copy-button-static')); +}); diff --git a/ui/tests/integration/components/nav-header-test.js b/ui/tests/integration/components/nav-header-test.js new file mode 100644 index 000000000000..e35e94b2d1ca --- /dev/null +++ b/ui/tests/integration/components/nav-header-test.js @@ -0,0 +1,39 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import { create } from 'ember-cli-page-object'; +import hbs from 'htmlbars-inline-precompile'; +import navHeader from 'vault/tests/pages/components/nav-header'; + +const component = create(navHeader); + +moduleForComponent('nav-header', 'Integration | Component | nav header', { + integration: true, + + beforeEach() { + component.setContext(this); + }, + + afterEach() { + component.removeContext(); + }, +}); + +test('it renders', function(assert) { + this.render(hbs` + {{#nav-header as |h|}} + {{#h.home}} + Home! + {{/h.home}} + {{#h.items}} + Some Items + {{/h.items}} + {{#h.main}} + Main stuff here + {{/h.main}} + {{/nav-header}} + `); + + assert.ok(component.ele, 'renders the outer element'); + assert.equal(component.homeText.trim(), 'Home!', 'renders home content'); + assert.equal(component.itemsText.trim(), 'Some Items', 'renders items content'); + assert.equal(component.mainText.trim(), 'Main stuff here', 'renders items content'); +}); diff --git a/ui/tests/integration/components/radial-progress-test.js b/ui/tests/integration/components/radial-progress-test.js new file mode 100644 index 000000000000..db7f43b444d3 --- /dev/null +++ b/ui/tests/integration/components/radial-progress-test.js @@ -0,0 +1,33 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import { create } from 'ember-cli-page-object'; +import hbs from 'htmlbars-inline-precompile'; +import radialProgress from 'vault/tests/pages/components/radial-progress'; + +const component = create(radialProgress); + +moduleForComponent('radial-progress', 'Integration | Component | radial progress', { + integration: true, + + beforeEach() { + component.setContext(this); + }, + + afterEach() { + component.removeContext(); + }, +}); + +test('it renders', function(assert) { + let circumference = 19 / 2 * Math.PI * 2; + this.render(hbs`{{radial-progress progressDecimal=0.5}}`); + + assert.equal(component.viewBox, '0 0 20 20'); + assert.equal(component.height, '20'); + assert.equal(component.width, '20'); + assert.equal(component.strokeWidth, '1'); + assert.equal(component.r, 19 / 2); + assert.equal(component.cx, 10); + assert.equal(component.cy, 10); + assert.equal(component.strokeDash, circumference); + assert.equal(component.strokeDashOffset, circumference * 0.5); +}); diff --git a/ui/tests/integration/components/shamir-flow-test.js b/ui/tests/integration/components/shamir-flow-test.js index e5f5fd199b20..54dd2acface9 100644 --- a/ui/tests/integration/components/shamir-flow-test.js +++ b/ui/tests/integration/components/shamir-flow-test.js @@ -8,11 +8,6 @@ let response = { complete: false, }; -let percent = () => { - const percent = response.progress / response.required * 100; - return percent.toFixed(4); -}; - let adapter = { foo() { return Ember.RSVP.resolve(response); @@ -34,14 +29,10 @@ moduleForComponent('shamir-flow', 'Integration | Component | shamir flow', { }); test('it renders', function(assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.on('myAction', function(val) { ... }); - this.render(hbs`{{shamir-flow formText="like whoa"}}`); assert.equal(this.$('form p').text().trim(), 'like whoa', 'renders formText inline'); - // Template block usage: this.render(hbs` {{#shamir-flow formText="like whoa"}}

whoa again

@@ -55,11 +46,7 @@ test('it renders', function(assert) { {{shamir-flow progress=1 threshold=5}} `); - assert.equal( - this.$('.shamir-progress .progress').val(), - 1 / 5 * 100, - 'renders progress bar with the appropriate value' - ); + assert.ok(this.$('.shamir-progress').text().includes('1/5 keys provided'), 'displays textual progress'); this.set('errors', ['first error', 'this is fine']); this.render(hbs` @@ -74,10 +61,9 @@ test('it sends data to the passed action', function(assert) { {{shamir-flow key=key action='foo' thresholdPath='required'}} `); this.$('[data-test-shamir-submit]').click(); - assert.equal( - this.$('.shamir-progress .progress').val(), - percent(), - 'renders progress bar with correct percent value' + assert.ok( + this.$('.shamir-progress').text().includes(`${response.progress}/${response.required} keys provided`), + 'displays the correct progress' ); }); @@ -103,9 +89,8 @@ test('it fetches progress on init when fetchOnInit is true', function(assert) { this.render(hbs` {{shamir-flow action='foo' fetchOnInit=true}} `); - assert.equal( - this.$('.shamir-progress .progress').val(), - percent(), - 'renders progress bar with correct percent value' + assert.ok( + this.$('.shamir-progress').text().includes(`${response.progress}/${response.required} keys provided`), + 'displays the correct progress' ); }); diff --git a/ui/tests/integration/components/upgrade-link-test.js b/ui/tests/integration/components/upgrade-link-test.js index c2e64f8c4e2f..7d44328cd082 100644 --- a/ui/tests/integration/components/upgrade-link-test.js +++ b/ui/tests/integration/components/upgrade-link-test.js @@ -7,10 +7,10 @@ moduleForComponent('upgrade-link', 'Integration | Component | upgrade link', { test('it renders with overlay', function(assert) { this.render(hbs` - - + + `); assert.equal(this.$('.upgrade-link-container button').text().trim(), 'upgrade', 'renders link content'); @@ -28,10 +28,10 @@ test('it renders with overlay', function(assert) { test('it adds custom classes', function(assert) { this.render(hbs` + - `); assert.equal( diff --git a/ui/tests/pages/components/hover-copy-button.js b/ui/tests/pages/components/hover-copy-button.js new file mode 100644 index 000000000000..360e93be8349 --- /dev/null +++ b/ui/tests/pages/components/hover-copy-button.js @@ -0,0 +1,9 @@ +import { attribute, isVisible, triggerable, focusable, text } from 'ember-cli-page-object'; + +export default { + focusContainer: focusable('.has-copy-button'), + mouseEnter: triggerable('mouseenter', '[data-test-tooltip-trigger]'), + tooltipText: text('[data-test-hover-copy-tooltip-text]'), + wrapperClass: attribute('class', '[data-test-hover-copy]'), + buttonIsVisible: isVisible('[data-test-hover-copy-button]'), +}; diff --git a/ui/tests/pages/components/nav-header.js b/ui/tests/pages/components/nav-header.js new file mode 100644 index 000000000000..de17c2be1826 --- /dev/null +++ b/ui/tests/pages/components/nav-header.js @@ -0,0 +1,8 @@ +import { text, isPresent } from 'ember-cli-page-object'; + +export default { + ele: isPresent('[data-test-navheader]'), + homeText: text('[data-test-navheader-home]'), + itemsText: text('[data-test-navheader-items]'), + mainText: text('[data-test-navheader-main]'), +}; diff --git a/ui/tests/pages/components/radial-progress.js b/ui/tests/pages/components/radial-progress.js new file mode 100644 index 000000000000..7d1e1acda205 --- /dev/null +++ b/ui/tests/pages/components/radial-progress.js @@ -0,0 +1,13 @@ +import { attribute } from 'ember-cli-page-object'; + +export default { + viewBox: attribute('viewBox', '[data-test-radial-progress]'), + height: attribute('height', '[data-test-radial-progress]'), + width: attribute('width', '[data-test-radial-progress]'), + cx: attribute('cx', '[data-test-path]'), + cy: attribute('cy', '[data-test-path]'), + r: attribute('r', '[data-test-path]'), + strokeWidth: attribute('stroke-width', '[data-test-path]'), + strokeDash: attribute('stroke-dasharray', '[data-test-progress]'), + strokeDashOffset: attribute('stroke-dashoffset', '[data-test-progress]'), +}; diff --git a/ui/tests/test-helper.js b/ui/tests/test-helper.js index 0680db4eaf5c..32bb2857f6cb 100644 --- a/ui/tests/test-helper.js +++ b/ui/tests/test-helper.js @@ -3,6 +3,8 @@ import './helpers/flash-message'; import { setResolver } from 'ember-qunit'; import { start } from 'ember-cli-qunit'; +import { useNativeEvents } from 'ember-cli-page-object/extend'; +useNativeEvents(); setResolver(resolver); start(); diff --git a/ui/yarn.lock b/ui/yarn.lock index 3e939e3cb3ad..07cfaaa2a612 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -192,6 +192,12 @@ amd-name-resolver@1.0.0: dependencies: ensure-posix-path "^1.0.1" +amd-name-resolver@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-1.2.0.tgz#fc41b3848824b557313897d71f8d5a0184fbe679" + dependencies: + ensure-posix-path "^1.0.1" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -463,6 +469,14 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + babel-core@^5.0.0: version "5.8.38" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-5.8.38.tgz#1fcaee79d7e61b750b00b8e54f6dfc9d0af86558" @@ -538,6 +552,30 @@ babel-core@^6.14.0, babel-core@^6.24.1: slash "^1.0.0" source-map "^0.5.0" +babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + babel-generator@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" @@ -551,6 +589,19 @@ babel-generator@^6.25.0: source-map "^0.5.0" trim-right "^1.0.1" +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" @@ -996,6 +1047,14 @@ babel-polyfill@^6.16.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" +babel-polyfill@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.26.0.tgz#379937abc67d7895970adc621f284cd966cf2153" + dependencies: + babel-runtime "^6.26.0" + core-js "^2.5.0" + regenerator-runtime "^0.10.5" + babel-preset-env@^1.5.1: version "1.6.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4" @@ -1031,6 +1090,41 @@ babel-preset-env@^1.5.1: invariant "^2.2.2" semver "^5.3.0" +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + babel-register@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f" @@ -1043,6 +1137,18 @@ babel-register@^6.24.1: mkdirp "^0.5.1" source-map-support "^0.4.2" +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" @@ -1050,6 +1156,13 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" +babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + babel-template@^6.24.1, babel-template@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" @@ -1060,6 +1173,16 @@ babel-template@^6.24.1, babel-template@^6.25.0: babylon "^6.17.2" lodash "^4.2.0" +babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + babel-traverse@^6.24.1, babel-traverse@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" @@ -1074,6 +1197,20 @@ babel-traverse@^6.24.1, babel-traverse@^6.25.0: invariant "^2.2.0" lodash "^4.2.0" +babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0: version "6.25.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" @@ -1083,6 +1220,15 @@ babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0: lodash "^4.2.0" to-fast-properties "^1.0.1" +babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + babel5-plugin-strip-class-callcheck@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/babel5-plugin-strip-class-callcheck/-/babel5-plugin-strip-class-callcheck-5.1.0.tgz#77d4a40c8614d367b8a21a53908159806dba5f91" @@ -1099,6 +1245,10 @@ babylon@^6.17.2: version "6.17.4" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a" +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + backbone@^1.1.2: version "1.3.3" resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.3.3.tgz#4cc80ea7cb1631ac474889ce40f2f8bc683b2999" @@ -1350,6 +1500,21 @@ broccoli-babel-transpiler@^6.1.2: rsvp "^3.5.0" workerpool "^2.2.1" +broccoli-babel-transpiler@^6.4.2: + version "6.4.3" + resolved "https://registry.yarnpkg.com/broccoli-babel-transpiler/-/broccoli-babel-transpiler-6.4.3.tgz#06e399298d41700cdc10d675b1d808a89ef6b2d0" + dependencies: + babel-core "^6.26.0" + broccoli-funnel "^2.0.1" + broccoli-merge-trees "^2.0.0" + broccoli-persistent-filter "^1.4.3" + clone "^2.0.0" + hash-for-dep "^1.2.3" + heimdalljs-logger "^0.1.7" + json-stable-stringify "^1.0.0" + rsvp "^4.8.2" + workerpool "^2.3.0" + broccoli-brocfile-loader@^0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/broccoli-brocfile-loader/-/broccoli-brocfile-loader-0.18.0.tgz#2e86021c805c34ffc8d29a2fb721cf273e819e4b" @@ -1613,7 +1778,7 @@ broccoli-persistent-filter@^1.0.3, broccoli-persistent-filter@^1.1.6, broccoli-p symlink-or-copy "^1.0.1" walk-sync "^0.3.1" -broccoli-persistent-filter@^1.1.5: +broccoli-persistent-filter@^1.1.5, broccoli-persistent-filter@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.3.tgz#3511bc52fc53740cda51621f58a28152d9911bc1" dependencies: @@ -1763,6 +1928,13 @@ browserslist@^2.11.3: caniuse-lite "^1.0.30000792" electron-to-chromium "^1.3.30" +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -1914,6 +2086,10 @@ caniuse-lite@^1.0.30000792, caniuse-lite@^1.0.30000805: version "1.0.30000830" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000830.tgz#cb96b8a2dd3cbfe04acea2af3c4e894249095328" +caniuse-lite@^1.0.30000844: + version "1.0.30000855" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000855.tgz#d5a26a9093b932d6266bf4ed9294b41b84945d14" + capture-exit@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-1.2.0.tgz#1c5fcc489fd0ab00d4f1ac7ae1072e3173fbab6f" @@ -2344,6 +2520,10 @@ convert-source-map@^1.1.0: version "1.5.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" +convert-source-map@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -2372,6 +2552,10 @@ core-js@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" +core-js@^2.5.0: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + core-object@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/core-object/-/core-object-1.1.0.tgz#86d63918733cf9da1a5aae729e62c0a88e66ad0a" @@ -2498,7 +2682,7 @@ debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.4. dependencies: ms "2.0.0" -debug@2.6.9, debug@^2.3.3: +debug@2.6.9, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -2716,6 +2900,10 @@ electron-to-chromium@^1.3.30: version "1.3.42" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz#95c33bf01d0cc405556aec899fe61fd4d76ea0f9" +electron-to-chromium@^1.3.47: + version "1.3.48" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz#d3b0d8593814044e092ece2108fc3ac9aea4b900" + ember-ajax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ember-ajax/-/ember-ajax-3.0.0.tgz#8f21e9da0c1d433cf879aa855fce464d517e9ab5" @@ -2735,29 +2923,28 @@ ember-api-actions@^0.1.8: dependencies: ember-cli-babel "^6.0.0" -ember-assign-helper@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ember-assign-helper/-/ember-assign-helper-0.1.1.tgz#217f221f37781b64657bd371d9da911768c3fbd1" +ember-assign-helper@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ember-assign-helper/-/ember-assign-helper-0.1.2.tgz#3d1d575f3d4457b3662b214d4c6e671bd462cad0" dependencies: - ember-cli-babel "^5.1.7" + ember-cli-babel "^6.0.0-beta.9" -ember-basic-dropdown-hover@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ember-basic-dropdown-hover/-/ember-basic-dropdown-hover-0.2.0.tgz#bbedb70a6858562bb6ad00c55c26406cac3a8264" +ember-basic-dropdown-hover@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/ember-basic-dropdown-hover/-/ember-basic-dropdown-hover-0.5.0.tgz#130b86d19442a8e8e855ea8009f7f991f59390f2" dependencies: - ember-assign-helper "0.1.1" - ember-basic-dropdown "^0.33.5" - ember-cli-babel "^5.1.7" - ember-cli-htmlbars "^1.1.1" + ember-assign-helper "^0.1.2" + ember-basic-dropdown "^1.0.0" + ember-cli-babel "^6.12.0" + ember-cli-htmlbars "^2.0.3" -ember-basic-dropdown@^0.33.5: - version "0.33.5" - resolved "https://registry.yarnpkg.com/ember-basic-dropdown/-/ember-basic-dropdown-0.33.5.tgz#39986d4cc6732edf43fb51eabb70790e99e8ae2c" +ember-basic-dropdown@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ember-basic-dropdown/-/ember-basic-dropdown-1.0.1.tgz#413f929572028d613024966726992fb45351880c" dependencies: - ember-cli-babel "^6.8.1" + ember-cli-babel "^6.12.0" ember-cli-htmlbars "^2.0.3" - ember-native-dom-helpers "^0.5.3" - ember-wormhole "^0.5.2" + ember-maybe-in-element "^0.1.3" ember-cli-autoprefixer@^0.8.1: version "0.8.1" @@ -2828,6 +3015,24 @@ ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.1.0, ember-cli-babel@^6.6.0, e clone "^2.0.0" ember-cli-version-checker "^2.0.0" +ember-cli-babel@^6.0.0-beta.9, ember-cli-babel@^6.11.0, ember-cli-babel@^6.12.0: + version "6.14.1" + resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-6.14.1.tgz#796339229035910b625593caffbc2683792ada68" + dependencies: + amd-name-resolver "1.2.0" + babel-plugin-debug-macros "^0.1.11" + babel-plugin-ember-modules-api-polyfill "^2.3.0" + babel-plugin-transform-es2015-modules-amd "^6.24.0" + babel-polyfill "^6.26.0" + babel-preset-env "^1.7.0" + broccoli-babel-transpiler "^6.4.2" + broccoli-debug "^0.6.4" + broccoli-funnel "^2.0.0" + broccoli-source "^1.1.0" + clone "^2.0.0" + ember-cli-version-checker "^2.1.2" + semver "^5.5.0" + ember-cli-broccoli-sane-watcher@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/ember-cli-broccoli-sane-watcher/-/ember-cli-broccoli-sane-watcher-2.0.4.tgz#f43f42f75b7509c212fb926cd9aea86ae19264c6" @@ -2921,7 +3126,7 @@ ember-cli-htmlbars-inline-precompile@^0.4.3: hash-for-dep "^1.0.2" silent-error "^1.1.0" -ember-cli-htmlbars@^1.0.10, ember-cli-htmlbars@^1.1.1: +ember-cli-htmlbars@^1.0.10: version "1.3.4" resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-1.3.4.tgz#461289724b34af372a6a0c4b6635819156963353" dependencies: @@ -3402,6 +3607,12 @@ ember-maybe-import-regenerator@^0.1.5: ember-cli-babel "^6.0.0-beta.4" regenerator-runtime "^0.9.5" +ember-maybe-in-element@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ember-maybe-in-element/-/ember-maybe-in-element-0.1.3.tgz#1c89be49246e580c1090336ad8be31e373f71b60" + dependencies: + ember-cli-babel "^6.11.0" + ember-moment@7.0.0-beta.5: version "7.0.0-beta.5" resolved "https://registry.yarnpkg.com/ember-moment/-/ember-moment-7.0.0-beta.5.tgz#b62c144d32f6ad0acaadd588ba93f4ddeb72ba89" @@ -3564,13 +3775,6 @@ ember-try@^0.2.15: rsvp "^3.0.17" semver "^5.1.0" -ember-wormhole@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/ember-wormhole/-/ember-wormhole-0.5.2.tgz#cc0ceb7db4f8b8da0fd852edc81d75cb1dcd92f1" - dependencies: - ember-cli-babel "^6.0.0" - ember-cli-htmlbars "^1.1.1" - encodeurl@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" @@ -4582,7 +4786,7 @@ globals@^6.4.0: version "6.4.1" resolved "https://registry.yarnpkg.com/globals/-/globals-6.4.1.tgz#8498032b3b6d1cc81eebc5f79690d8fe29fabf4f" -globals@^9.0.0, globals@^9.14.0, globals@^9.17.0: +globals@^9.0.0, globals@^9.14.0, globals@^9.17.0, globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -5364,7 +5568,7 @@ js-tokens@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-1.0.1.tgz#cc435a5c8b94ad15acb7983140fc80182c89aeae" -js-tokens@^3.0.0: +js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -5429,7 +5633,7 @@ json5@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/json5/-/json5-0.4.0.tgz#054352e4c4c80c86c0923877d449de176a732c8d" -json5@^0.5.0: +json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -6671,7 +6875,7 @@ path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" -path-is-absolute@^1.0.0: +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -6875,6 +7079,10 @@ private@^0.1.6, private@~0.1.5: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" +private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" @@ -7127,10 +7335,14 @@ regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" -regenerator-runtime@^0.10.0: +regenerator-runtime@^0.10.0, regenerator-runtime@^0.10.5: version "0.10.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + regenerator-runtime@^0.9.5: version "0.9.6" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.9.6.tgz#d33eb95d0d2001a4be39659707c51b0cb71ce029" @@ -7439,6 +7651,10 @@ rsvp@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.7.0.tgz#dc1b0b1a536f7dec9d2be45e0a12ad4197c9fd96" +rsvp@^4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.2.tgz#9d5647108735784eb13418cdddb56f75b919d722" + rsvp@~3.0.6: version "3.0.21" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.0.21.tgz#49c588fe18ef293bcd0ab9f4e6756e6ac433359f" @@ -7549,7 +7765,7 @@ semver@^4.1.0: version "4.3.6" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" -semver@^5.4.1: +semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" @@ -7801,6 +8017,12 @@ source-map-support@^0.2.10: dependencies: source-map "0.1.32" +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + source-map-support@^0.4.2: version "0.4.15" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" @@ -7831,6 +8053,10 @@ source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" +source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -8238,7 +8464,7 @@ to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" -to-fast-properties@^1.0.0, to-fast-properties@^1.0.1: +to-fast-properties@^1.0.0, to-fast-properties@^1.0.1, to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -8645,6 +8871,12 @@ workerpool@^2.2.1: dependencies: object-assign "4.1.1" +workerpool@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-2.3.0.tgz#86c5cbe946b55e7dc9d12b1936c8801a6e2d744d" + dependencies: + object-assign "4.1.1" + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"