diff --git a/ui/.storybook/preview-head.html b/ui/.storybook/preview-head.html index 9c353e54b153..13cafd050917 100644 --- a/ui/.storybook/preview-head.html +++ b/ui/.storybook/preview-head.html @@ -1,4 +1,6 @@ - + + + diff --git a/ui/app/app.js b/ui/app/app.js index 8b963f8e10cb..a215b634c98a 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -8,10 +8,27 @@ defineModifier(); let App; +/* eslint-disable ember/avoid-leaking-state-in-ember-objects */ App = Application.extend({ modulePrefix: config.modulePrefix, podModulePrefix: config.podModulePrefix, Resolver, + engines: { + replication: { + dependencies: { + services: [ + 'auth', + 'flash-messages', + 'namespace', + 'replication-mode', + 'router', + 'store', + 'version', + 'wizard', + ], + }, + }, + }, }); loadInitializers(App, config.modulePrefix); diff --git a/ui/app/components/empty-state.js b/ui/app/components/empty-state.js deleted file mode 100644 index 04e6c3d213c7..000000000000 --- a/ui/app/components/empty-state.js +++ /dev/null @@ -1,6 +0,0 @@ -import OuterHTML from './outer-html'; - -export default OuterHTML.extend({ - title: null, - message: null, -}); diff --git a/ui/app/components/info-table-row.js b/ui/app/components/info-table-row.js deleted file mode 100644 index 1be591196dc0..000000000000 --- a/ui/app/components/info-table-row.js +++ /dev/null @@ -1,34 +0,0 @@ -import { typeOf } from '@ember/utils'; -import { computed } from '@ember/object'; -import { or } from '@ember/object/computed'; -import Component from '@ember/component'; - -export default Component.extend({ - 'data-test-component': 'info-table-row', - classNames: ['info-table-row'], - isVisible: or('alwaysRender', 'value'), - - /* - * @param boolean - * indicates if the component content should be always be rendered. - * when false, the value of `value` will be used to determine if the component should render - */ - alwaysRender: false, - - /* - * @param string - * the display name for the value - * - */ - label: null, - - /* - * - * the value of the data passed in - by default the content of the component will only show if there is a value - */ - value: null, - - valueIsBoolean: computed('value', function() { - return typeOf(this.get('value')) === 'boolean'; - }), -}); diff --git a/ui/app/components/popup-menu.js b/ui/app/components/popup-menu.js deleted file mode 100644 index 3f263270c4e2..000000000000 --- a/ui/app/components/popup-menu.js +++ /dev/null @@ -1,5 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({ - tagName: 'span', -}); diff --git a/ui/app/controllers/vault/cluster/replication/mode/secondaries/add.js b/ui/app/controllers/vault/cluster/replication/mode/secondaries/add.js deleted file mode 100644 index 01da58dffbe3..000000000000 --- a/ui/app/controllers/vault/cluster/replication/mode/secondaries/add.js +++ /dev/null @@ -1,3 +0,0 @@ -import ReplicationController from '../../../replication'; - -export default ReplicationController.extend(); diff --git a/ui/app/controllers/vault/cluster/replication/mode/secondaries/index.js b/ui/app/controllers/vault/cluster/replication/mode/secondaries/index.js deleted file mode 100644 index 01da58dffbe3..000000000000 --- a/ui/app/controllers/vault/cluster/replication/mode/secondaries/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import ReplicationController from '../../../replication'; - -export default ReplicationController.extend(); diff --git a/ui/app/controllers/vault/cluster/replication/mode/secondaries/revoke.js b/ui/app/controllers/vault/cluster/replication/mode/secondaries/revoke.js deleted file mode 100644 index 9be89e9d34fb..000000000000 --- a/ui/app/controllers/vault/cluster/replication/mode/secondaries/revoke.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from '../../../replication'; diff --git a/ui/app/helpers/includes.js b/ui/app/helpers/includes.js deleted file mode 100644 index ff61d3586b9d..000000000000 --- a/ui/app/helpers/includes.js +++ /dev/null @@ -1,7 +0,0 @@ -import { helper as buildHelper } from '@ember/component/helper'; - -export function includes([haystack, needle]) { - return haystack.includes(needle); -} - -export default buildHelper(includes); diff --git a/ui/app/helpers/reduce-to-array.js b/ui/app/helpers/reduce-to-array.js deleted file mode 100644 index b6d76d9e2b24..000000000000 --- a/ui/app/helpers/reduce-to-array.js +++ /dev/null @@ -1,17 +0,0 @@ -import { helper as buildHelper } from '@ember/component/helper'; -import { isNone, typeOf } from '@ember/utils'; - -export function reduceToArray(params) { - return params.reduce(function(result, param) { - if (isNone(param)) { - return result; - } - if (typeOf(param) === 'array') { - return result.concat(param); - } else { - return result.concat([param]); - } - }, []); -} - -export default buildHelper(reduceToArray); diff --git a/ui/app/initializers/enable-engines.js b/ui/app/initializers/enable-engines.js new file mode 100644 index 000000000000..858f36b06d08 --- /dev/null +++ b/ui/app/initializers/enable-engines.js @@ -0,0 +1,13 @@ +import config from '../config/environment'; + +export function initialize(/* application */) { + // attach mount hooks to the environment config + // context will be the router DSL + config.addRootMounts = function() { + this.mount('replication'); + }; +} + +export default { + initialize, +}; diff --git a/ui/app/mixins/cluster-route.js b/ui/app/mixins/cluster-route.js index 9b814c99ed14..2b7ff244ed23 100644 --- a/ui/app/mixins/cluster-route.js +++ b/ui/app/mixins/cluster-route.js @@ -13,6 +13,7 @@ export { INIT, UNSEAL, AUTH, CLUSTER, DR_REPLICATION_SECONDARY }; export default Mixin.create({ auth: service(), + store: service(), transitionToTargetRoute(transition) { const targetRoute = this.targetRouteName(transition); @@ -28,7 +29,7 @@ export default Mixin.create({ }, clusterModel() { - return this.modelFor(CLUSTER); + return this.modelFor(CLUSTER) || this.store.peekRecord('cluster', 'vault'); }, authToken() { diff --git a/ui/app/router.js b/ui/app/router.js index b1b87d87904e..de87a5433917 100644 --- a/ui/app/router.js +++ b/ui/app/router.js @@ -114,22 +114,9 @@ Router.map(function() { this.route('edit', { path: '/:policy_name/edit' }); }); this.route('replication-dr-promote'); - this.route('replication', function() { - this.route('index', { path: '/' }); - this.route('mode', { path: '/:replication_mode' }, function() { - //details - this.route('index', { path: '/' }); - this.route('manage'); - this.route('secondaries', function() { - this.route('add', { path: '/add' }); - this.route('revoke', { path: '/revoke' }); - this.route('config-show', { path: '/config/show/:secondary_id' }); - this.route('config-edit', { path: '/config/edit/:secondary_id' }); - this.route('config-create', { path: '/config/create/:secondary_id' }); - }); - }); - }); - + if (config.addRootMounts) { + config.addRootMounts.call(this); + } this.route('not-found', { path: '/*path' }); }); this.route('not-found', { path: '/*path' }); diff --git a/ui/app/routes/vault/cluster/replication/mode/index.js b/ui/app/routes/vault/cluster/replication/mode/index.js deleted file mode 100644 index b2663787983c..000000000000 --- a/ui/app/routes/vault/cluster/replication/mode/index.js +++ /dev/null @@ -1,13 +0,0 @@ -import { inject as service } from '@ember/service'; -import Route from '@ember/routing/route'; - -export default Route.extend({ - replicationMode: service(), - beforeModel() { - const replicationMode = this.paramsFor('vault.cluster.replication.mode').replication_mode; - this.get('replicationMode').setMode(replicationMode); - }, - model() { - return this.modelFor('vault.cluster.replication.mode'); - }, -}); diff --git a/ui/app/templates/components/auth-form.hbs b/ui/app/templates/components/auth-form.hbs index 8d1f204d3958..0f6412a11333 100644 --- a/ui/app/templates/components/auth-form.hbs +++ b/ui/app/templates/components/auth-form.hbs @@ -1,7 +1,7 @@
{{#if showLoading}}
- {{partial 'svg/vault-loading'}} +
{{/if}} {{#if hasMethodsWithPath}} diff --git a/ui/app/templates/components/replication-actions.hbs b/ui/app/templates/components/replication-actions.hbs deleted file mode 100644 index 08c0c031cec4..000000000000 --- a/ui/app/templates/components/replication-actions.hbs +++ /dev/null @@ -1,5 +0,0 @@ -{{message-error errors=errors}} -{{#if loading}} -{{else}} - {{partial (concat 'partials/replication/' selectedAction)}} -{{/if}} diff --git a/ui/app/templates/components/replication-mode-summary.hbs b/ui/app/templates/components/replication-mode-summary.hbs deleted file mode 100644 index d3fb34c191d6..000000000000 --- a/ui/app/templates/components/replication-mode-summary.hbs +++ /dev/null @@ -1 +0,0 @@ -{{partial partialName}} diff --git a/ui/app/templates/components/replication-summary.hbs b/ui/app/templates/components/replication-summary.hbs deleted file mode 100644 index 3d0b2bad304e..000000000000 --- a/ui/app/templates/components/replication-summary.hbs +++ /dev/null @@ -1,24 +0,0 @@ -{{#if (not version.hasDRReplication)}} - {{upgrade-page title="Replication"}} -{{else if (or cluster.allReplicationDisabled cluster.replicationAttrs.replicationDisabled)}} - {{partial 'partials/replication/enable'}} -{{else if showModeSummary}} - {{partial 'partials/replication/mode-summary'}} -{{else}} - {{#if (eq replicationAttrs.mode 'initializing')}} - The cluster is initializing replication. This may take some time. - {{else}} - {{info-table-row label="Mode" value=replicationAttrs.mode}} - {{info-table-row label="Replication set" value=replicationAttrs.clusterId}} - {{info-table-row label="Secondary ID" value=replicationAttrs.secondaryId}} - {{info-table-row label="State" value=replicationAttrs.state}} - {{info-table-row label="Primary cluster address" value=replicationAttrs.primaryClusterAddr}} - {{info-table-row label="Replication state" value=replicationAttrs.replicationState}} - {{info-table-row label="Last WAL entry" value=replicationAttrs.lastWAL}} - {{info-table-row label="Last Remote WAL entry" value=replicationAttrs.lastRemoteWAL}} - {{info-table-row label="Merkle root index" value=replicationAttrs.merkleRoot}} - {{#if replicationAttrs.syncProgress}} - {{info-table-row label="Sync progress" value=(concat replicationAttrs.syncProgress.progress '/' replicationAttrs.syncProgress.total)}} - {{/if}} - {{/if}} -{{/if}} diff --git a/ui/app/templates/components/toggle-button.hbs b/ui/app/templates/components/toggle-button.hbs deleted file mode 100644 index bd1fb85ab6e6..000000000000 --- a/ui/app/templates/components/toggle-button.hbs +++ /dev/null @@ -1,5 +0,0 @@ -{{#if isOpen}} - {{i-con glyph='chevron-up' exludeIconClass=true}}  {{openLabel}} -{{else}} - {{i-con glyph='chevron-down' exludeIconClass=true}}  {{closedLabel}} -{{/if}} diff --git a/ui/app/templates/components/transit-key-action/datakey.hbs b/ui/app/templates/components/transit-key-action/datakey.hbs index d85f8e915d0f..54540edc9504 100644 --- a/ui/app/templates/components/transit-key-action/datakey.hbs +++ b/ui/app/templates/components/transit-key-action/datakey.hbs @@ -103,7 +103,7 @@ id="bits" onchange={{action (mut bits) value="target.value"}} > - {{#each (reduce-to-array 128 256 512) as |bitOption|}} + {{#each (array 128 256 512) as |bitOption|}} diff --git a/ui/app/templates/components/transit-key-action/export.hbs b/ui/app/templates/components/transit-key-action/export.hbs index 579ae1f95bc2..3b1bc8e6760a 100644 --- a/ui/app/templates/components/transit-key-action/export.hbs +++ b/ui/app/templates/components/transit-key-action/export.hbs @@ -1,7 +1,7 @@ -
{{#if (or keys wrappedToken) }}
diff --git a/ui/app/templates/partials/replication/enable.hbs b/ui/app/templates/partials/replication/enable.hbs deleted file mode 100644 index 007d1db99c01..000000000000 --- a/ui/app/templates/partials/replication/enable.hbs +++ /dev/null @@ -1,258 +0,0 @@ - - -

- {{#if initialReplicationMode}} - {{#if (eq initialReplicationMode 'dr')}} - Enable Disaster Recovery Replication - {{else if (eq initialReplicationMode 'performance')}} - Enable Performance Replication - {{/if}} - {{else}} - Enable Replication - {{/if}} -

-
-
- - -
- {{message-error errors=errors}} - {{#if initialReplicationMode}} - {{#if (eq initialReplicationMode 'dr')}} -

- {{i-con class="is-medium" glyph="replication" size=24}} - Disaster Recovery (DR) Replication -

-

- DR is designed to protect against catastrophic failure of entire clusters. Secondaries do not forward service requests (until they are elected and become a new primary). -

- {{else if (eq initialReplicationMode 'performance')}} -

- {{i-con class="is-medium" glyph="perf-replication" size=20}} - Performance Replication -

- {{#if (not version.hasPerfReplication)}} -

- Performance Replication is a feature of {{#upgrade-link pageName="Performance Replication"}}Vault Enterprise Premium{{/upgrade-link}} -

- {{else}} -

- Performance replication scales workloads horizontally across clusters to make requests faster. Local secondaries handle read requests but forward writes to the primary to be handled. -

- {{/if}} - {{/if}} - {{else}} -

- - In both Performance and Disaster Recovery (DR) Replication, secondaries share the underlying configuration, policies, and supporting secrets as their primary cluster. -

-
-
- -
-
- -
-
- {{/if}} -
-
- -
-
- -
- {{#if (eq mode 'secondary')}} - - {{/if}} -
- {{#if (eq mode 'primary')}} - {{#if cluster.canEnablePrimary}} -
- -
- {{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. -

-
- {{else}} -

- The token you are using is not authorized to enable primary replication. -

- {{/if}} - {{else}} - {{#if cluster.canEnableSecondary}} - {{#if (and - (eq replicationMode 'dr') - (not cluster.performance.replicationDisabled) - version.hasPerfReplication - ) - }} -
- {{toggle-button - toggleTarget=this - toggleAttr='showExplanation' - openLabel="Disable Performance Replication in order to enable this cluster as a DR secondary." - closedLabel="Disable Performance Replication in order to enable this cluster as a DR secondary." - class="has-text-danger" - }} - {{#if showExplanation}} -

- When running as a DR Secondary Vault is read only. - For this reason, we don't allow other Replication modes to operate at the same time. This cluster is also - currently operating as a Performance {{capitalize cluster.performance.modeForUrl}}. -

- {{/if}} -
- {{else}} -
- -
- {{textarea value=token id="secondary-token" name="secondary-token" class="textarea"}} -
-
-
- -
- {{input value=primary_api_addr id="primary_api_addr" name="primary_api_addr" class="input"}} -
-

- {{#if (and token (not tokenIncludesAPIAddr))}} - The supplied token does not contain an embedded address for the primary cluster. Please enter the primary cluster's API address (normal Vault address). - {{else}} - Set this to the API address (normal Vault address) to override the - value embedded in the token. - {{/if}} -

-
-
- -
- {{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. -

-
-

- Note: If both CA file and CA path are not given, they default to system CA roots. -

- {{/if}} - {{else}} -

The token you are using is not authorized to enable secondary replication.

- {{/if}} - {{/if}} -
- {{#if (or (and (eq mode 'primary') cluster.canEnablePrimary) (and (eq mode 'secondary') cluster.canEnableSecondary))}} -
-
- -
-
- {{/if}} - diff --git a/ui/app/templates/partials/replication/mode-summary.hbs b/ui/app/templates/partials/replication/mode-summary.hbs deleted file mode 100644 index 555d31426c50..000000000000 --- a/ui/app/templates/partials/replication/mode-summary.hbs +++ /dev/null @@ -1,57 +0,0 @@ - - -

- Replication -

-
-
-
-

- {{i-con class="has-text-grey is-medium" glyph="replication" size=20}} - Disaster Recovery (DR) -

- {{#if cluster.dr.replicationEnabled}} - {{#link-to - "vault.cluster.replication.mode.index" - "dr" - class="link-plain" - }} - {{replication-mode-summary - mode="dr" - cluster=cluster - tagName="span" - }} - {{/link-to}} - {{else}} - {{replication-mode-summary - mode="dr" - cluster=cluster - tagName="div" - }} - {{/if}} -
-
-

- {{i-con class="has-text-grey is-medium" glyph="perf-replication" size=20}} - Performance -

- {{#if cluster.dr.replicationEnabled}} - {{#link-to - "vault.cluster.replication.mode.index" - "performance" - class="link-plain" - }} - {{replication-mode-summary - mode="performance" - cluster=cluster - tagName="span" - }} - {{/link-to}} - {{else}} - {{replication-mode-summary - mode="performance" - cluster=cluster - tagName="div" - }} - {{/if}} -
diff --git a/ui/app/templates/partials/replication/replication-mode-summary-menu.hbs b/ui/app/templates/partials/replication/replication-mode-summary-menu.hbs deleted file mode 100644 index 18eb45904fd7..000000000000 --- a/ui/app/templates/partials/replication/replication-mode-summary-menu.hbs +++ /dev/null @@ -1,44 +0,0 @@ -
-
- {{#if replicationUnsupported}} - Unsupported - {{else if replicationEnabled}} - - {{capitalize modeForUrl}} - - {{#if secondaryId}} - - - {{secondaryId}} - - - {{/if}} - - - {{clusterIdDisplay}} - - - {{else if (and (eq mode 'performance') (not version.hasPerfReplication))}} - Learn more - {{else if auth.currentToken}} - Enable {{if (eq mode 'performance') 'Performance' 'DR'}} - {{else}} - Not enabled - {{/if}} -
-
- {{#if replicationEnabled}} - {{#if (get cluster (concat mode 'StateGlyph'))}} - - {{i-con size=16 glyph=(get cluster (concat mode 'StateGlyph'))}} - - {{else if syncProgress}} - - {{syncProgress.progress}} of {{syncProgress.total}} keys - - {{/if}} - {{else}} - - {{/if}} -
-
diff --git a/ui/app/templates/partials/replication/replication-mode-summary.hbs b/ui/app/templates/partials/replication/replication-mode-summary.hbs deleted file mode 100644 index fe972ed49ea6..000000000000 --- a/ui/app/templates/partials/replication/replication-mode-summary.hbs +++ /dev/null @@ -1,53 +0,0 @@ -
-
- {{#if (and (eq mode 'performance') (not version.hasPerfReplication))}} -

- Performance Replication is a feature of Vault Enterprise Premium. -

-

- {{#upgrade-link linkClass="button is-ghost has-icon-right" pageName="Performance Replication"}} - Learn more - {{i-con glyph="chevron-right"}} - {{/upgrade-link}} -

- {{else if replicationEnabled}} -
- Enabled -
- - {{capitalize modeForUrl}} - - {{#if secondaryId}} - - - {{secondaryId}} - - - {{/if}} - - - {{clusterIdDisplay}} - - - {{else}} -

- {{#if (eq mode 'dr')}} - DR is designed to protect against catastrophic failure of entire clusters. Secondaries do not forward service requests (until they are elected and become a new primary). - {{else}} - Performance Replication scales workloads horizontally across clusters to make requests faster. Local secondaries handle read requests but forward writes to the primary to be handled. - {{/if}} -

- {{/if}} -
-
-
- {{#if replicationDisabled}} - {{#link-to "vault.cluster.replication.mode.index" cluster.name mode class="button is-primary"}} - Enable - {{/link-to}} - {{else if (eq mode 'dr')}} - {{cluster.drReplicationStateDisplay}} - {{else if (eq mode 'performance')}} - {{cluster.perfReplicationStateDisplay}} - {{/if}} -
diff --git a/ui/app/templates/partials/tools/hash.hbs b/ui/app/templates/partials/tools/hash.hbs index a59e48908ab8..2c29283a0047 100644 --- a/ui/app/templates/partials/tools/hash.hbs +++ b/ui/app/templates/partials/tools/hash.hbs @@ -73,7 +73,7 @@ id="format" onchange={{action (mut format) value="target.value"}} > - {{#each (reduce-to-array 'base64' 'hex') as |formatOption|}} + {{#each (array 'base64' 'hex') as |formatOption|}} diff --git a/ui/app/templates/vault/cluster/loading.hbs b/ui/app/templates/vault/cluster/loading.hbs index b8b5ad854a52..23a871bd9450 100644 --- a/ui/app/templates/vault/cluster/loading.hbs +++ b/ui/app/templates/vault/cluster/loading.hbs @@ -1 +1 @@ -{{partial "partials/loading"}} + diff --git a/ui/app/templates/vault/cluster/policies/loading.hbs b/ui/app/templates/vault/cluster/policies/loading.hbs index b8b5ad854a52..23a871bd9450 100644 --- a/ui/app/templates/vault/cluster/policies/loading.hbs +++ b/ui/app/templates/vault/cluster/policies/loading.hbs @@ -1 +1 @@ -{{partial "partials/loading"}} + diff --git a/ui/app/templates/vault/cluster/policy/loading.hbs b/ui/app/templates/vault/cluster/policy/loading.hbs index b8b5ad854a52..23a871bd9450 100644 --- a/ui/app/templates/vault/cluster/policy/loading.hbs +++ b/ui/app/templates/vault/cluster/policy/loading.hbs @@ -1 +1 @@ -{{partial "partials/loading"}} + diff --git a/ui/app/templates/vault/cluster/replication/mode/manage.hbs b/ui/app/templates/vault/cluster/replication/mode/manage.hbs deleted file mode 100644 index 17fb025b9673..000000000000 --- a/ui/app/templates/vault/cluster/replication/mode/manage.hbs +++ /dev/null @@ -1,11 +0,0 @@ -{{#each (replication-action-for-mode replicationMode model.replicationAttrs.modeForUrl) as |replicationAction index|}} - {{#if (get model (concat 'can' (camelize replicationAction)))}} -
- {{replication-actions - replicationMode=replicationMode - model=model - selectedAction=replicationAction - }} -
- {{/if}} -{{/each}} diff --git a/ui/ember-cli-build.js b/ui/ember-cli-build.js index 228b35a7b964..0b7ea0f707a7 100644 --- a/ui/ember-cli-build.js +++ b/ui/ember-cli-build.js @@ -2,6 +2,7 @@ 'use strict'; const EmberApp = require('ember-cli/lib/broccoli/ember-app'); +const config = require('./config/environment')(); const environment = EmberApp.env(); const isProd = environment === 'production'; @@ -9,6 +10,12 @@ const isTest = environment === 'test'; module.exports = function(defaults) { var app = new EmberApp(defaults, { + assetLoader: { + generateURI: function(filePath) { + return `${config.rootURL.replace(/\/$/, '')}${filePath}`; + }, + }, + codemirror: { modes: ['javascript', 'ruby'], keyMaps: ['sublime'], diff --git a/ui/app/components/alert-banner.js b/ui/lib/core/addon/components/alert-banner.js similarity index 86% rename from ui/app/components/alert-banner.js rename to ui/lib/core/addon/components/alert-banner.js index 1d27a499eae7..d6f3901c747b 100644 --- a/ui/app/components/alert-banner.js +++ b/ui/lib/core/addon/components/alert-banner.js @@ -1,6 +1,7 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; -import { messageTypes } from 'vault/helpers/message-types'; +import { messageTypes } from 'core/helpers/message-types'; +import layout from '../templates/components/alert-banner'; /** * @module AlertBanner @@ -17,6 +18,7 @@ import { messageTypes } from 'vault/helpers/message-types'; */ export default Component.extend({ + layout, type: null, message: null, yieldWithoutColumn: false, diff --git a/ui/app/components/alert-inline.js b/ui/lib/core/addon/components/alert-inline.js similarity index 86% rename from ui/app/components/alert-inline.js rename to ui/lib/core/addon/components/alert-inline.js index 61638995ce06..fbcdc8277a7f 100644 --- a/ui/app/components/alert-inline.js +++ b/ui/lib/core/addon/components/alert-inline.js @@ -1,6 +1,7 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; -import { messageTypes } from 'vault/helpers/message-types'; +import { messageTypes } from 'core/helpers/message-types'; +import layout from '../templates/components/alert-inline'; /** * @module AlertInline @@ -17,6 +18,7 @@ import { messageTypes } from 'vault/helpers/message-types'; */ export default Component.extend({ + layout, type: null, message: null, diff --git a/ui/app/components/confirm-action.js b/ui/lib/core/addon/components/confirm-action.js similarity index 100% rename from ui/app/components/confirm-action.js rename to ui/lib/core/addon/components/confirm-action.js diff --git a/ui/app/components/doc-link.js b/ui/lib/core/addon/components/doc-link.js similarity index 58% rename from ui/app/components/doc-link.js rename to ui/lib/core/addon/components/doc-link.js index 35a9ac0b1a1c..39bc73d4ef61 100644 --- a/ui/app/components/doc-link.js +++ b/ui/lib/core/addon/components/doc-link.js @@ -2,6 +2,19 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; import hbs from 'htmlbars-inline-precompile'; +/** + * @module DocLink + * `DocLink` components are used to render anchor links to relevant Vault documentation. + * + * @example + * ```js + Learn about KV v2 + * ``` + * + * @param path="/"{String} - The path to documentation on vaultproject.io that the component should link to. + * + */ + export default Component.extend({ tagName: 'a', classNames: ['doc-link'], diff --git a/ui/lib/core/addon/components/empty-state.js b/ui/lib/core/addon/components/empty-state.js new file mode 100644 index 000000000000..6d7c6d550bca --- /dev/null +++ b/ui/lib/core/addon/components/empty-state.js @@ -0,0 +1,24 @@ +import Component from '@ember/component'; +import layout from '../templates/components/empty-state'; + +/** + * @module EmptyState + * `EmptyState` components are used to render a helpful message and any necessary content when a user + * encounters a state that would usually be blank. + * + * @example + * ```js + * + * ``` + * + * @param title=null{String} - A short label for the empty state + * @param message=null{String} - A description of why a user might be seeing the empty state and possibly instructions for actions they may take. + * + */ + +export default Component.extend({ + layout, + tagName: '', + title: null, + message: null, +}); diff --git a/ui/lib/core/addon/components/info-table-row.js b/ui/lib/core/addon/components/info-table-row.js new file mode 100644 index 000000000000..ef6895c25ab4 --- /dev/null +++ b/ui/lib/core/addon/components/info-table-row.js @@ -0,0 +1,35 @@ +import { typeOf } from '@ember/utils'; +import { computed } from '@ember/object'; +import { or } from '@ember/object/computed'; +import Component from '@ember/component'; +import layout from '../templates/components/info-table-row'; + +/** + * @module InfoTableRow + * `InfoTableRow` displays a label and a value in a table-row style manner. The component is responsive so + * that the value breaks under the label on smaller viewports. + * + * @example + * ```js + * + * ``` + * + * @param value=null {any} - The the data to be displayed - by default the content of the component will only show if there is a value. Also note that special handling is given to boolean values - they will render `Yes` for true and `No` for false. + * @param label=null {string} - The display name for the value. + * @param alwaysRender=false {Boolean} - Indicates if the component content should be always be rendered. When false, the value of `value` will be used to determine if the component should render. + * + */ +export default Component.extend({ + layout, + 'data-test-component': 'info-table-row', + classNames: ['info-table-row'], + isVisible: or('alwaysRender', 'value'), + + alwaysRender: false, + label: null, + value: null, + + valueIsBoolean: computed('value', function() { + return typeOf(this.get('value')) === 'boolean'; + }), +}); diff --git a/ui/lib/core/addon/components/layout-loading.js b/ui/lib/core/addon/components/layout-loading.js new file mode 100644 index 000000000000..5723895b6898 --- /dev/null +++ b/ui/lib/core/addon/components/layout-loading.js @@ -0,0 +1,17 @@ +import Component from '@ember/component'; +import layout from '../templates/components/layout-loading'; + +/** + * @module LayoutLoading + * `LayoutLoading` displays the `VaultLogoSpinner` component in a centered full-page layout. + * + * @example + * ```js + * + * ``` + */ + +export default Component.extend({ + layout, + tagName: '', +}); diff --git a/ui/app/components/message-error.js b/ui/lib/core/addon/components/message-error.js similarity index 59% rename from ui/app/components/message-error.js rename to ui/lib/core/addon/components/message-error.js index 6003dce9fd30..c2f94b1e6175 100644 --- a/ui/app/components/message-error.js +++ b/ui/lib/core/addon/components/message-error.js @@ -1,11 +1,25 @@ import { computed } from '@ember/object'; import Component from '@ember/component'; +import layout from '../templates/components/message-error'; +/** + * @module MessageError + * `MessageError` extracts an error from a model or a passed error and displays it using the `AlertBanner` component. + * + * @example + * ```js + * + * ``` + * + * @param model=null{DS.Model} - An Ember data model that will be used to bind error statest to the internal + * `errors` property. + * @param errors=null{Array} - An array of error strings to show. + * @param errorMessage=null{String} - An Error string to display. + */ export default Component.extend({ + layout, model: null, - errors: computed(function() { - return []; - }), + errors: null, errorMessage: null, displayErrors: computed( diff --git a/ui/app/components/page-header-level-left.js b/ui/lib/core/addon/components/page-header-level-left.js similarity index 54% rename from ui/app/components/page-header-level-left.js rename to ui/lib/core/addon/components/page-header-level-left.js index 4798652642ba..6442967e6687 100644 --- a/ui/app/components/page-header-level-left.js +++ b/ui/lib/core/addon/components/page-header-level-left.js @@ -1,5 +1,7 @@ import Component from '@ember/component'; +import layout from '../templates/components/page-header-level-left'; export default Component.extend({ + layout, tagName: '', }); diff --git a/ui/app/components/page-header-level-right.js b/ui/lib/core/addon/components/page-header-level-right.js similarity index 54% rename from ui/app/components/page-header-level-right.js rename to ui/lib/core/addon/components/page-header-level-right.js index 4798652642ba..6d5c6221107b 100644 --- a/ui/app/components/page-header-level-right.js +++ b/ui/lib/core/addon/components/page-header-level-right.js @@ -1,5 +1,7 @@ import Component from '@ember/component'; +import layout from '../templates/components/page-header-level-right'; export default Component.extend({ + layout, tagName: '', }); diff --git a/ui/app/components/page-header-top.js b/ui/lib/core/addon/components/page-header-top.js similarity index 100% rename from ui/app/components/page-header-top.js rename to ui/lib/core/addon/components/page-header-top.js diff --git a/ui/app/components/page-header.js b/ui/lib/core/addon/components/page-header.js similarity index 62% rename from ui/app/components/page-header.js rename to ui/lib/core/addon/components/page-header.js index 9a92d16670f6..0c6040701b05 100644 --- a/ui/app/components/page-header.js +++ b/ui/lib/core/addon/components/page-header.js @@ -1,6 +1,8 @@ import Component from '@ember/component'; +import layout from '../templates/components/page-header'; export default Component.extend({ + layout, tagName: '', hasLevel: true, }); diff --git a/ui/lib/core/addon/components/popup-menu.js b/ui/lib/core/addon/components/popup-menu.js new file mode 100644 index 000000000000..916cfb8439a5 --- /dev/null +++ b/ui/lib/core/addon/components/popup-menu.js @@ -0,0 +1,21 @@ +import Component from '@ember/component'; +import layout from '../templates/components/popup-menu'; + +/** + * @module PopupMenu + * `PopupMenu` displays a button that when pressed will toggle open a menu that is yielded in the content + * block. + * + * @example + * ```js + * + * ``` + * + * @param contentClass=''{String} A class that will be applied to the yielded content of the popup. + */ + +export default Component.extend({ + layout, + contentClass: '', + tagName: 'span', +}); diff --git a/ui/app/components/replication-mode-summary.js b/ui/lib/core/addon/components/replication-mode-summary.js similarity index 84% rename from ui/app/components/replication-mode-summary.js rename to ui/lib/core/addon/components/replication-mode-summary.js index cd7716b8ee05..7e19a887eeea 100644 --- a/ui/app/components/replication-mode-summary.js +++ b/ui/lib/core/addon/components/replication-mode-summary.js @@ -2,6 +2,7 @@ import { inject as service } from '@ember/service'; import { equal } from '@ember/object/computed'; import { getProperties, get, computed } from '@ember/object'; import Component from '@ember/component'; +import layout from '../templates/components/replication-mode-summary'; const replicationAttr = function(attr) { return computed('mode', `cluster.{dr,performance}.${attr}`, function() { @@ -10,6 +11,7 @@ const replicationAttr = function(attr) { }); }; export default Component.extend({ + layout, version: service(), router: service(), namespace: service(), @@ -24,11 +26,7 @@ export default Component.extend({ return 'https://www.hashicorp.com/products/vault'; } if (this.get('replicationEnabled') || display === 'menu') { - return this.get('router').urlFor( - 'vault.cluster.replication.mode.index', - this.get('cluster.name'), - mode - ); + return this.get('router').urlFor('vault.cluster.replication.mode.index', this.get('cluster.id'), mode); } return null; }), @@ -50,9 +48,4 @@ export default Component.extend({ clusterIdDisplay: replicationAttr('clusterIdDisplay'), mode: null, cluster: null, - partialName: computed('display', function() { - return this.get('display') === 'menu' - ? 'partials/replication/replication-mode-summary-menu' - : 'partials/replication/replication-mode-summary'; - }), }); diff --git a/ui/app/components/toggle-button.js b/ui/lib/core/addon/components/toggle-button.js similarity index 95% rename from ui/app/components/toggle-button.js rename to ui/lib/core/addon/components/toggle-button.js index 9272ecc490d3..4b33eb2389f7 100644 --- a/ui/app/components/toggle-button.js +++ b/ui/lib/core/addon/components/toggle-button.js @@ -1,5 +1,6 @@ import Component from '@ember/component'; import { set, get, defineProperty, computed } from '@ember/object'; +import layout from '../templates/components/toggle-button'; /** * @module ToggleButton @@ -22,6 +23,7 @@ import { set, get, defineProperty, computed } from '@ember/object'; * @param closedLabel=More options {String} - The message to display when the toggle is closed. */ export default Component.extend({ + layout, tagName: 'button', type: 'button', toggleTarget: null, diff --git a/ui/app/components/ttl-picker.js b/ui/lib/core/addon/components/ttl-picker.js similarity index 72% rename from ui/app/components/ttl-picker.js rename to ui/lib/core/addon/components/ttl-picker.js index 403b324f6bad..2cfefba6afe2 100644 --- a/ui/app/components/ttl-picker.js +++ b/ui/lib/core/addon/components/ttl-picker.js @@ -3,16 +3,39 @@ import EmberError from '@ember/error'; import Component from '@ember/component'; import { set, computed } from '@ember/object'; import Duration from 'Duration.js'; +import layout from '../templates/components/ttl-picker'; const ERROR_MESSAGE = 'TTLs must be specified in whole number increments, please enter a whole number.'; +/** + * @module TtlPicker + * `TtlPicker` components are used to expand and collapse content with a toggle. + * + * @example + * ```js + + * ``` + * + * @param labelClass="" {String} - A CSS class to add to the label. + * @param labelText="TTL" {String} - The text content of the label associated with the widget. + * @param initialValue=null {Number} - The starting value of the TTL; + * @param setDefaultValue=true {Boolean} - If true, the component will trigger onChange on the initial + * render, causing a value to be set. + * @param onChange=Function.prototype{Function} - The function to call when the value of the ttl changes. + * @param outputSeconds=false{Boolean} - If true, the component will trigger onChange with a value + * converted to seconds instead of a Golang duration string. + */ export default Component.extend({ + layout, 'data-test-component': 'ttl-picker', classNames: 'field', - setDefaultValue: true, + onChange: () => {}, + setDefaultValue: true, labelText: 'TTL', labelClass: '', + ouputSeconds: false, + time: 30, unit: 'm', initialValue: null, @@ -26,8 +49,6 @@ export default Component.extend({ ]; }), - ouputSeconds: false, - convertToSeconds(time, unit) { const toSeconds = { s: 1, diff --git a/ui/app/components/upgrade-page.js b/ui/lib/core/addon/components/upgrade-page.js similarity index 82% rename from ui/app/components/upgrade-page.js rename to ui/lib/core/addon/components/upgrade-page.js index c9c974507f50..0b4c29d4a382 100644 --- a/ui/app/components/upgrade-page.js +++ b/ui/lib/core/addon/components/upgrade-page.js @@ -1,7 +1,9 @@ import Component from '@ember/component'; import { computed } from '@ember/object'; +import layout from '../templates/components/upgrade-page'; export default Component.extend({ + layout, title: 'Vault Enterprise', featureName: computed('title', function() { let title = this.get('title'); diff --git a/ui/lib/core/addon/components/vault-logo-spinner.js b/ui/lib/core/addon/components/vault-logo-spinner.js new file mode 100644 index 000000000000..270837619a8f --- /dev/null +++ b/ui/lib/core/addon/components/vault-logo-spinner.js @@ -0,0 +1,17 @@ +import Component from '@ember/component'; +import layout from '../templates/components/vault-logo-spinner'; + +/** + * @module VaultLogoSpinner + * `VaultLogoSpinner` displays an animated Vault logo to use for loading screens. + * + * @example + * ```js + * + * ``` + */ + +export default Component.extend({ + layout, + tagName: '', +}); diff --git a/ui/app/helpers/has-feature.js b/ui/lib/core/addon/helpers/has-feature.js similarity index 100% rename from ui/app/helpers/has-feature.js rename to ui/lib/core/addon/helpers/has-feature.js diff --git a/ui/app/helpers/is-active-route.js b/ui/lib/core/addon/helpers/is-active-route.js similarity index 100% rename from ui/app/helpers/is-active-route.js rename to ui/lib/core/addon/helpers/is-active-route.js diff --git a/ui/app/helpers/message-types.js b/ui/lib/core/addon/helpers/message-types.js similarity index 100% rename from ui/app/helpers/message-types.js rename to ui/lib/core/addon/helpers/message-types.js diff --git a/ui/app/helpers/set-flash-message.js b/ui/lib/core/addon/helpers/set-flash-message.js similarity index 100% rename from ui/app/helpers/set-flash-message.js rename to ui/lib/core/addon/helpers/set-flash-message.js diff --git a/ui/app/templates/components/alert-banner.hbs b/ui/lib/core/addon/templates/components/alert-banner.hbs similarity index 97% rename from ui/app/templates/components/alert-banner.hbs rename to ui/lib/core/addon/templates/components/alert-banner.hbs index 5287fa0184b0..f412619cbc22 100644 --- a/ui/app/templates/components/alert-banner.hbs +++ b/ui/lib/core/addon/templates/components/alert-banner.hbs @@ -1,12 +1,14 @@
+ {{!-- + --}}
{{#if yieldWithoutColumn}} {{yield}} diff --git a/ui/app/templates/components/alert-inline.hbs b/ui/lib/core/addon/templates/components/alert-inline.hbs similarity index 93% rename from ui/app/templates/components/alert-inline.hbs rename to ui/lib/core/addon/templates/components/alert-inline.hbs index 4b841feca4c1..db9236503052 100644 --- a/ui/app/templates/components/alert-inline.hbs +++ b/ui/lib/core/addon/templates/components/alert-inline.hbs @@ -1,8 +1,10 @@ +{{!-- +--}}

{{@message}}

diff --git a/ui/app/templates/components/empty-state.hbs b/ui/lib/core/addon/templates/components/empty-state.hbs similarity index 100% rename from ui/app/templates/components/empty-state.hbs rename to ui/lib/core/addon/templates/components/empty-state.hbs diff --git a/ui/app/templates/components/info-table-row.hbs b/ui/lib/core/addon/templates/components/info-table-row.hbs similarity index 100% rename from ui/app/templates/components/info-table-row.hbs rename to ui/lib/core/addon/templates/components/info-table-row.hbs diff --git a/ui/app/templates/partials/loading.hbs b/ui/lib/core/addon/templates/components/layout-loading.hbs similarity index 87% rename from ui/app/templates/partials/loading.hbs rename to ui/lib/core/addon/templates/components/layout-loading.hbs index 7bd1c71de6f0..b144ff68bf68 100644 --- a/ui/app/templates/partials/loading.hbs +++ b/ui/lib/core/addon/templates/components/layout-loading.hbs @@ -2,7 +2,7 @@
- {{partial 'svg/vault-loading'}} +
diff --git a/ui/app/templates/components/message-error.hbs b/ui/lib/core/addon/templates/components/message-error.hbs similarity index 100% rename from ui/app/templates/components/message-error.hbs rename to ui/lib/core/addon/templates/components/message-error.hbs diff --git a/ui/app/templates/components/page-header-level-left.hbs b/ui/lib/core/addon/templates/components/page-header-level-left.hbs similarity index 100% rename from ui/app/templates/components/page-header-level-left.hbs rename to ui/lib/core/addon/templates/components/page-header-level-left.hbs diff --git a/ui/app/templates/components/page-header-level-right.hbs b/ui/lib/core/addon/templates/components/page-header-level-right.hbs similarity index 100% rename from ui/app/templates/components/page-header-level-right.hbs rename to ui/lib/core/addon/templates/components/page-header-level-right.hbs diff --git a/ui/app/templates/components/page-header.hbs b/ui/lib/core/addon/templates/components/page-header.hbs similarity index 100% rename from ui/app/templates/components/page-header.hbs rename to ui/lib/core/addon/templates/components/page-header.hbs diff --git a/ui/app/templates/components/popup-menu.hbs b/ui/lib/core/addon/templates/components/popup-menu.hbs similarity index 97% rename from ui/app/templates/components/popup-menu.hbs rename to ui/lib/core/addon/templates/components/popup-menu.hbs index 5d7ad1e606c7..18d841be5257 100644 --- a/ui/app/templates/components/popup-menu.hbs +++ b/ui/lib/core/addon/templates/components/popup-menu.hbs @@ -1,11 +1,13 @@ {{#basic-dropdown class="popup-menu" horizontalPosition="auto-right" verticalPosition="below" onOpen=onOpen as |d|}} {{#d.trigger tagName="button" class=(concat "popup-menu-trigger button is-ghost" (if d.isOpen " is-active")) data-test-popup-menu-trigger=true}} + {{!-- {{i-con glyph="more" class="has-text-black auto-width" size=16 aria-label="More options" }} + --}} {{/d.trigger}} {{#d.content class=(concat "popup-menu-content " contentClass)}}
diff --git a/ui/lib/core/addon/templates/components/replication-mode-summary.hbs b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs new file mode 100644 index 000000000000..339e8d400385 --- /dev/null +++ b/ui/lib/core/addon/templates/components/replication-mode-summary.hbs @@ -0,0 +1,101 @@ +{{#if (eq display 'menu')}} +
+
+ {{#if replicationUnsupported}} + Unsupported + {{else if replicationEnabled}} + + {{capitalize modeForUrl}} + + {{#if secondaryId}} + + + {{secondaryId}} + + + {{/if}} + + + {{clusterIdDisplay}} + + + {{else if (and (eq mode 'performance') (not (has-feature "Performance Replication")))}} + Learn more + {{else if auth.currentToken}} + Enable {{if (eq mode 'performance') 'Performance' 'DR'}} + {{else}} + Not enabled + {{/if}} +
+
+ {{#if replicationEnabled}} + {{#if (get cluster (concat mode 'StateGlyph'))}} + + {{i-con size=16 glyph=(get cluster (concat mode 'StateGlyph'))}} + + {{else if syncProgress}} + + {{syncProgress.progress}} of {{syncProgress.total}} keys + + {{/if}} + {{else}} + + {{/if}} +
+
+{{else}} +
+
+ {{#if (and (eq mode 'performance') (not (has-feature "Performance Replication")))}} +

+ Performance Replication is a feature of Vault Enterprise Premium. +

+

+ {{#upgrade-link linkClass="button is-ghost has-icon-right" pageName="Performance Replication"}} + Learn more + {{i-con glyph="chevron-right"}} + {{/upgrade-link}} +

+ {{else if replicationEnabled}} +
+ Enabled +
+ + {{capitalize modeForUrl}} + + {{#if secondaryId}} + + + {{secondaryId}} + + + {{/if}} + + + {{clusterIdDisplay}} + + + {{else}} +

+ {{#if (eq mode 'dr')}} + DR is designed to protect against catastrophic failure of entire clusters. Secondaries do not forward service requests (until they are elected and become a new primary). + {{else}} + Performance Replication scales workloads horizontally across clusters to make requests faster. Local secondaries handle read requests but forward writes to the primary to be handled. + {{/if}} +

+ {{/if}} +
+
+
+ {{#if replicationDisabled}} + {{#link-to "vault.cluster.replication.mode.index" cluster.name mode class="button is-primary"}} + Enable + {{/link-to}} + {{else if (eq mode 'dr')}} + {{cluster.drReplicationStateDisplay}} + {{else if (eq mode 'performance')}} + {{cluster.perfReplicationStateDisplay}} + {{/if}} +
+ +{{/if}} diff --git a/ui/lib/core/addon/templates/components/toggle-button.hbs b/ui/lib/core/addon/templates/components/toggle-button.hbs new file mode 100644 index 000000000000..25e7652c11ac --- /dev/null +++ b/ui/lib/core/addon/templates/components/toggle-button.hbs @@ -0,0 +1,5 @@ +{{#if isOpen}} +{{!--{{i-con glyph='chevron-up' exludeIconClass=true}}--}}  {{openLabel}} +{{else}} +{{!--{{i-con glyph='chevron-down' exludeIconClass=true}}--}}  {{closedLabel}} +{{/if}} diff --git a/ui/app/templates/components/ttl-picker.hbs b/ui/lib/core/addon/templates/components/ttl-picker.hbs similarity index 100% rename from ui/app/templates/components/ttl-picker.hbs rename to ui/lib/core/addon/templates/components/ttl-picker.hbs diff --git a/ui/app/templates/components/upgrade-page.hbs b/ui/lib/core/addon/templates/components/upgrade-page.hbs similarity index 100% rename from ui/app/templates/components/upgrade-page.hbs rename to ui/lib/core/addon/templates/components/upgrade-page.hbs diff --git a/ui/app/templates/svg/vault-loading.hbs b/ui/lib/core/addon/templates/components/vault-logo-spinner.hbs similarity index 100% rename from ui/app/templates/svg/vault-loading.hbs rename to ui/lib/core/addon/templates/components/vault-logo-spinner.hbs diff --git a/ui/app/utils/b64.js b/ui/lib/core/addon/utils/b64.js similarity index 100% rename from ui/app/utils/b64.js rename to ui/lib/core/addon/utils/b64.js diff --git a/ui/lib/core/app/components/alert-banner.js b/ui/lib/core/app/components/alert-banner.js new file mode 100644 index 000000000000..64985f13c61f --- /dev/null +++ b/ui/lib/core/app/components/alert-banner.js @@ -0,0 +1 @@ +export { default } from 'core/components/alert-banner'; diff --git a/ui/lib/core/app/components/alert-inline.js b/ui/lib/core/app/components/alert-inline.js new file mode 100644 index 000000000000..c0de083f8351 --- /dev/null +++ b/ui/lib/core/app/components/alert-inline.js @@ -0,0 +1 @@ +export { default } from 'core/components/alert-inline'; diff --git a/ui/lib/core/app/components/confirm-action.js b/ui/lib/core/app/components/confirm-action.js new file mode 100644 index 000000000000..59524549311a --- /dev/null +++ b/ui/lib/core/app/components/confirm-action.js @@ -0,0 +1 @@ +export { default } from 'core/components/confirm-action'; diff --git a/ui/lib/core/app/components/doc-link.js b/ui/lib/core/app/components/doc-link.js new file mode 100644 index 000000000000..d495e84f123a --- /dev/null +++ b/ui/lib/core/app/components/doc-link.js @@ -0,0 +1 @@ +export { default } from 'core/components/doc-link'; diff --git a/ui/lib/core/app/components/empty-state.js b/ui/lib/core/app/components/empty-state.js new file mode 100644 index 000000000000..5ec2afae9da6 --- /dev/null +++ b/ui/lib/core/app/components/empty-state.js @@ -0,0 +1 @@ +export { default } from 'core/components/empty-state'; diff --git a/ui/lib/core/app/components/i-con.js b/ui/lib/core/app/components/i-con.js new file mode 100644 index 000000000000..583d6b68f007 --- /dev/null +++ b/ui/lib/core/app/components/i-con.js @@ -0,0 +1 @@ +export { default } from 'core/components/i-con'; diff --git a/ui/lib/core/app/components/info-table-row.js b/ui/lib/core/app/components/info-table-row.js new file mode 100644 index 000000000000..318bcafc269d --- /dev/null +++ b/ui/lib/core/app/components/info-table-row.js @@ -0,0 +1 @@ +export { default } from 'core/components/info-table-row'; diff --git a/ui/lib/core/app/components/layout-loading.js b/ui/lib/core/app/components/layout-loading.js new file mode 100644 index 000000000000..ebdfe539c975 --- /dev/null +++ b/ui/lib/core/app/components/layout-loading.js @@ -0,0 +1 @@ +export { default } from 'core/components/layout-loading'; diff --git a/ui/lib/core/app/components/message-error.js b/ui/lib/core/app/components/message-error.js new file mode 100644 index 000000000000..f1aa6ebdaa43 --- /dev/null +++ b/ui/lib/core/app/components/message-error.js @@ -0,0 +1 @@ +export { default } from 'core/components/message-error'; diff --git a/ui/lib/core/app/components/page-header-level-left.js b/ui/lib/core/app/components/page-header-level-left.js new file mode 100644 index 000000000000..4d219df1e381 --- /dev/null +++ b/ui/lib/core/app/components/page-header-level-left.js @@ -0,0 +1 @@ +export { default } from 'core/components/page-header-level-left'; diff --git a/ui/lib/core/app/components/page-header-level-right.js b/ui/lib/core/app/components/page-header-level-right.js new file mode 100644 index 000000000000..3eb8615b7021 --- /dev/null +++ b/ui/lib/core/app/components/page-header-level-right.js @@ -0,0 +1 @@ +export { default } from 'core/components/page-header-level-right'; diff --git a/ui/lib/core/app/components/page-header-top.js b/ui/lib/core/app/components/page-header-top.js new file mode 100644 index 000000000000..c7bf111a7fc5 --- /dev/null +++ b/ui/lib/core/app/components/page-header-top.js @@ -0,0 +1 @@ +export { default } from 'core/components/page-header-top'; diff --git a/ui/lib/core/app/components/page-header.js b/ui/lib/core/app/components/page-header.js new file mode 100644 index 000000000000..ce908e6c702f --- /dev/null +++ b/ui/lib/core/app/components/page-header.js @@ -0,0 +1 @@ +export { default } from 'core/components/page-header'; diff --git a/ui/lib/core/app/components/popup-menu.js b/ui/lib/core/app/components/popup-menu.js new file mode 100644 index 000000000000..ea03c2430e2a --- /dev/null +++ b/ui/lib/core/app/components/popup-menu.js @@ -0,0 +1 @@ +export { default } from 'core/components/popup-menu'; diff --git a/ui/lib/core/app/components/replication-mode-summary.js b/ui/lib/core/app/components/replication-mode-summary.js new file mode 100644 index 000000000000..fbe45992db1d --- /dev/null +++ b/ui/lib/core/app/components/replication-mode-summary.js @@ -0,0 +1 @@ +export { default } from 'core/components/replication-mode-summary'; diff --git a/ui/lib/core/app/components/toggle-button.js b/ui/lib/core/app/components/toggle-button.js new file mode 100644 index 000000000000..c3272665914d --- /dev/null +++ b/ui/lib/core/app/components/toggle-button.js @@ -0,0 +1 @@ +export { default } from 'core/components/toggle-button'; diff --git a/ui/lib/core/app/components/ttl-picker.js b/ui/lib/core/app/components/ttl-picker.js new file mode 100644 index 000000000000..bd9cd6441045 --- /dev/null +++ b/ui/lib/core/app/components/ttl-picker.js @@ -0,0 +1 @@ +export { default } from 'core/components/ttl-picker'; diff --git a/ui/lib/core/app/components/upgrade-page.js b/ui/lib/core/app/components/upgrade-page.js new file mode 100644 index 000000000000..bf9f0e794035 --- /dev/null +++ b/ui/lib/core/app/components/upgrade-page.js @@ -0,0 +1 @@ +export { default } from 'core/components/upgrade-page'; diff --git a/ui/lib/core/app/components/vault-logo-spinner.js b/ui/lib/core/app/components/vault-logo-spinner.js new file mode 100644 index 000000000000..f6b77c9dee19 --- /dev/null +++ b/ui/lib/core/app/components/vault-logo-spinner.js @@ -0,0 +1 @@ +export { default } from 'core/components/vault-logo-spinner'; diff --git a/ui/lib/core/app/helpers/has-feature.js b/ui/lib/core/app/helpers/has-feature.js new file mode 100644 index 000000000000..c5a79021c2c6 --- /dev/null +++ b/ui/lib/core/app/helpers/has-feature.js @@ -0,0 +1 @@ +export { default } from 'core/helpers/has-feature'; diff --git a/ui/lib/core/app/helpers/is-active-route.js b/ui/lib/core/app/helpers/is-active-route.js new file mode 100644 index 000000000000..da955ae2581f --- /dev/null +++ b/ui/lib/core/app/helpers/is-active-route.js @@ -0,0 +1 @@ +export { default, isActiveRoute } from 'core/helpers/is-active-route'; diff --git a/ui/lib/core/app/helpers/message-types.js b/ui/lib/core/app/helpers/message-types.js new file mode 100644 index 000000000000..a2ebe335680e --- /dev/null +++ b/ui/lib/core/app/helpers/message-types.js @@ -0,0 +1 @@ +export { default, messageTypes, MESSAGE_TYPES } from 'core/helpers/message-types'; diff --git a/ui/lib/core/app/helpers/set-flash-message.js b/ui/lib/core/app/helpers/set-flash-message.js new file mode 100644 index 000000000000..2e1442757827 --- /dev/null +++ b/ui/lib/core/app/helpers/set-flash-message.js @@ -0,0 +1 @@ +export { default, setFlashMessage } from 'core/helpers/set-flash-message'; diff --git a/ui/lib/core/app/utils/b64.js b/ui/lib/core/app/utils/b64.js new file mode 100644 index 000000000000..cf7ae9479711 --- /dev/null +++ b/ui/lib/core/app/utils/b64.js @@ -0,0 +1 @@ +export { encodeString, decodeString } from 'core/utils/b64'; diff --git a/ui/lib/core/index.js b/ui/lib/core/index.js new file mode 100644 index 000000000000..6a11283511b1 --- /dev/null +++ b/ui/lib/core/index.js @@ -0,0 +1,8 @@ +/* eslint-disable */ + +module.exports = { + name: require('./package').name, + isDevelopingAddon() { + return true; + }, +}; diff --git a/ui/lib/core/package.json b/ui/lib/core/package.json new file mode 100644 index 000000000000..280ef5d77ab2 --- /dev/null +++ b/ui/lib/core/package.json @@ -0,0 +1,21 @@ +{ + "name": "core", + "keywords": [ + "ember-addon" + ], + "dependencies": { + "ember-auto-import": "*", + "ember-basic-dropdown": "*", + "ember-cli-htmlbars": "*", + "ember-cli-htmlbars-inline-precompile": "*", + "ember-cli-babel": "*", + "ember-cli-clipboard": "*", + "ember-radio-button": "*", + "ember-composable-helpers": "*", + "ember-cli-string-helpers": "*", + "ember-truth-helpers": "*", + "ember-concurrency": "*", + "base64-js": "*", + "Duration.js": "*" + } +} diff --git a/ui/lib/replication/addon/.eslintrc.js b/ui/lib/replication/addon/.eslintrc.js new file mode 100644 index 000000000000..6ae3faf54afe --- /dev/null +++ b/ui/lib/replication/addon/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + env: { + node: false, + browser: true, + }, +}; diff --git a/ui/app/components/mount-filter-config-list.js b/ui/lib/replication/addon/components/mount-filter-config-list.js similarity index 100% rename from ui/app/components/mount-filter-config-list.js rename to ui/lib/replication/addon/components/mount-filter-config-list.js diff --git a/ui/lib/replication/addon/components/replication-action-demote.js b/ui/lib/replication/addon/components/replication-action-demote.js new file mode 100644 index 000000000000..e84bd0148647 --- /dev/null +++ b/ui/lib/replication/addon/components/replication-action-demote.js @@ -0,0 +1,3 @@ +import Actions from './replication-actions-single'; + +export default Actions.extend(); diff --git a/ui/lib/replication/addon/components/replication-action-disable.js b/ui/lib/replication/addon/components/replication-action-disable.js new file mode 100644 index 000000000000..e84bd0148647 --- /dev/null +++ b/ui/lib/replication/addon/components/replication-action-disable.js @@ -0,0 +1,3 @@ +import Actions from './replication-actions-single'; + +export default Actions.extend(); diff --git a/ui/lib/replication/addon/components/replication-action-promote.js b/ui/lib/replication/addon/components/replication-action-promote.js new file mode 100644 index 000000000000..e84bd0148647 --- /dev/null +++ b/ui/lib/replication/addon/components/replication-action-promote.js @@ -0,0 +1,3 @@ +import Actions from './replication-actions-single'; + +export default Actions.extend(); diff --git a/ui/lib/replication/addon/components/replication-action-recover.js b/ui/lib/replication/addon/components/replication-action-recover.js new file mode 100644 index 000000000000..e84bd0148647 --- /dev/null +++ b/ui/lib/replication/addon/components/replication-action-recover.js @@ -0,0 +1,3 @@ +import Actions from './replication-actions-single'; + +export default Actions.extend(); diff --git a/ui/lib/replication/addon/components/replication-action-reindex.js b/ui/lib/replication/addon/components/replication-action-reindex.js new file mode 100644 index 000000000000..e84bd0148647 --- /dev/null +++ b/ui/lib/replication/addon/components/replication-action-reindex.js @@ -0,0 +1,3 @@ +import Actions from './replication-actions-single'; + +export default Actions.extend(); diff --git a/ui/lib/replication/addon/components/replication-action-update-primary.js b/ui/lib/replication/addon/components/replication-action-update-primary.js new file mode 100644 index 000000000000..e84bd0148647 --- /dev/null +++ b/ui/lib/replication/addon/components/replication-action-update-primary.js @@ -0,0 +1,3 @@ +import Actions from './replication-actions-single'; + +export default Actions.extend(); diff --git a/ui/lib/replication/addon/components/replication-actions-single.js b/ui/lib/replication/addon/components/replication-actions-single.js new file mode 100644 index 000000000000..90573cbea1ca --- /dev/null +++ b/ui/lib/replication/addon/components/replication-actions-single.js @@ -0,0 +1,14 @@ +import Component from '@ember/component'; + +export default Component.extend({ + onSubmit() {}, + replicationMode: null, + replicationDisplayMode: null, + model: null, + + actions: { + onSubmit() { + return this.onSubmit(...arguments); + }, + }, +}); diff --git a/ui/app/components/replication-actions.js b/ui/lib/replication/addon/components/replication-actions.js similarity index 88% rename from ui/app/components/replication-actions.js rename to ui/lib/replication/addon/components/replication-actions.js index c2ad4ae8334f..6e4e17b4f120 100644 --- a/ui/app/components/replication-actions.js +++ b/ui/lib/replication/addon/components/replication-actions.js @@ -1,7 +1,7 @@ import { alias } from '@ember/object/computed'; import Component from '@ember/component'; import { computed } from '@ember/object'; -import ReplicationActions from 'vault/mixins/replication-actions'; +import ReplicationActions from 'replication/mixins/replication-actions'; const DEFAULTS = { token: null, @@ -15,18 +15,13 @@ const DEFAULTS = { export default Component.extend(ReplicationActions, DEFAULTS, { replicationMode: null, - selectedAction: null, - tagName: 'form', + model: null, + cluster: alias('model'), didReceiveAttrs() { this._super(...arguments); }, - model: null, - cluster: alias('model'), - loading: false, - onSubmit: null, - reset() { if (!this || this.isDestroyed || this.isDestroying) { return; diff --git a/ui/app/components/replication-secondaries.js b/ui/lib/replication/addon/components/replication-secondaries.js similarity index 100% rename from ui/app/components/replication-secondaries.js rename to ui/lib/replication/addon/components/replication-secondaries.js diff --git a/ui/app/components/replication-summary.js b/ui/lib/replication/addon/components/replication-summary.js similarity index 93% rename from ui/app/components/replication-summary.js rename to ui/lib/replication/addon/components/replication-summary.js index 745722a6d9a2..34479653a4e5 100644 --- a/ui/app/components/replication-summary.js +++ b/ui/lib/replication/addon/components/replication-summary.js @@ -2,8 +2,8 @@ import { inject as service } from '@ember/service'; import { alias } from '@ember/object/computed'; import { get, computed } from '@ember/object'; import Component from '@ember/component'; -import decodeConfigFromJWT from 'vault/utils/decode-config-from-jwt'; -import ReplicationActions from 'vault/mixins/replication-actions'; +import decodeConfigFromJWT from 'replication/utils/decode-config-from-jwt'; +import ReplicationActions from 'replication/mixins/replication-actions'; import { task } from 'ember-concurrency'; const DEFAULTS = { diff --git a/ui/app/controllers/vault/cluster/replication.js b/ui/lib/replication/addon/controllers/application.js similarity index 90% rename from ui/app/controllers/vault/cluster/replication.js rename to ui/lib/replication/addon/controllers/application.js index be9c1dbdac16..794c2edefee1 100644 --- a/ui/app/controllers/vault/cluster/replication.js +++ b/ui/lib/replication/addon/controllers/application.js @@ -44,7 +44,6 @@ export default Controller.extend(DEFAULTS, { submitSuccess(resp, action) { const cluster = this.get('model'); - const store = this.get('store'); if (!cluster) { return; } @@ -58,18 +57,11 @@ export default Controller.extend(DEFAULTS, { primary_api_addr: null, primary_cluster_addr: null, }); - return cluster; + return cluster.reload(); } this.reset(); - return store - .adapterFor('cluster') - .replicationStatus() - .then(status => { - return store.pushPayload('cluster', status); - }) - .finally(() => { - this.set('loading', false); - }); + this.send('refresh'); + return; }, submitHandler(action, clusterMode, data, event) { @@ -125,5 +117,9 @@ export default Controller.extend(DEFAULTS, { id: null, }); }, + refresh() { + // bubble to the route + return true; + }, }, }); diff --git a/ui/app/controllers/vault/cluster/replication/index.js b/ui/lib/replication/addon/controllers/index.js similarity index 100% rename from ui/app/controllers/vault/cluster/replication/index.js rename to ui/lib/replication/addon/controllers/index.js diff --git a/ui/app/controllers/vault/cluster/replication/mode.js b/ui/lib/replication/addon/controllers/mode.js similarity index 100% rename from ui/app/controllers/vault/cluster/replication/mode.js rename to ui/lib/replication/addon/controllers/mode.js diff --git a/ui/app/controllers/vault/cluster/replication/mode/index.js b/ui/lib/replication/addon/controllers/mode/index.js similarity index 100% rename from ui/app/controllers/vault/cluster/replication/mode/index.js rename to ui/lib/replication/addon/controllers/mode/index.js diff --git a/ui/app/controllers/vault/cluster/replication/mode/manage.js b/ui/lib/replication/addon/controllers/mode/manage.js similarity index 100% rename from ui/app/controllers/vault/cluster/replication/mode/manage.js rename to ui/lib/replication/addon/controllers/mode/manage.js diff --git a/ui/app/controllers/vault/cluster/replication/mode/secondaries.js b/ui/lib/replication/addon/controllers/mode/secondaries.js similarity index 100% rename from ui/app/controllers/vault/cluster/replication/mode/secondaries.js rename to ui/lib/replication/addon/controllers/mode/secondaries.js diff --git a/ui/lib/replication/addon/controllers/mode/secondaries/add.js b/ui/lib/replication/addon/controllers/mode/secondaries/add.js new file mode 100644 index 000000000000..6a80887200ba --- /dev/null +++ b/ui/lib/replication/addon/controllers/mode/secondaries/add.js @@ -0,0 +1,3 @@ +import ReplicationController from 'replication/controllers/application'; + +export default ReplicationController.extend(); diff --git a/ui/app/controllers/vault/cluster/replication/mode/secondaries/config-create.js b/ui/lib/replication/addon/controllers/mode/secondaries/config-create.js similarity index 100% rename from ui/app/controllers/vault/cluster/replication/mode/secondaries/config-create.js rename to ui/lib/replication/addon/controllers/mode/secondaries/config-create.js diff --git a/ui/app/controllers/vault/cluster/replication/mode/secondaries/config-edit.js b/ui/lib/replication/addon/controllers/mode/secondaries/config-edit.js similarity index 85% rename from ui/app/controllers/vault/cluster/replication/mode/secondaries/config-edit.js rename to ui/lib/replication/addon/controllers/mode/secondaries/config-edit.js index 90c2703f17fa..ab56eea31594 100644 --- a/ui/app/controllers/vault/cluster/replication/mode/secondaries/config-edit.js +++ b/ui/lib/replication/addon/controllers/mode/secondaries/config-edit.js @@ -24,12 +24,8 @@ export default Controller.extend({ const flash = this.get('flashMessages'); const id = config.id; const redirectArgs = isDelete - ? [ - 'vault.cluster.replication.mode.secondaries', - this.model.cluster.get('name'), - this.get('replicationMode'), - ] - : ['vault.cluster.replication.mode.secondaries.config-show', id]; + ? ['mode.secondaries', this.get('replicationMode')] + : ['mode.secondaries.config-show', id]; const modelMethod = isDelete ? config.destroyRecord : config.save; modelMethod diff --git a/ui/app/controllers/vault/cluster/replication/mode/secondaries/config-show.js b/ui/lib/replication/addon/controllers/mode/secondaries/config-show.js similarity index 100% rename from ui/app/controllers/vault/cluster/replication/mode/secondaries/config-show.js rename to ui/lib/replication/addon/controllers/mode/secondaries/config-show.js diff --git a/ui/lib/replication/addon/controllers/mode/secondaries/index.js b/ui/lib/replication/addon/controllers/mode/secondaries/index.js new file mode 100644 index 000000000000..6a80887200ba --- /dev/null +++ b/ui/lib/replication/addon/controllers/mode/secondaries/index.js @@ -0,0 +1,3 @@ +import ReplicationController from 'replication/controllers/application'; + +export default ReplicationController.extend(); diff --git a/ui/lib/replication/addon/controllers/mode/secondaries/revoke.js b/ui/lib/replication/addon/controllers/mode/secondaries/revoke.js new file mode 100644 index 000000000000..6a80887200ba --- /dev/null +++ b/ui/lib/replication/addon/controllers/mode/secondaries/revoke.js @@ -0,0 +1,3 @@ +import ReplicationController from 'replication/controllers/application'; + +export default ReplicationController.extend(); diff --git a/ui/app/controllers/vault/cluster/replication/replication-mode.js b/ui/lib/replication/addon/controllers/replication-mode.js similarity index 60% rename from ui/app/controllers/vault/cluster/replication/replication-mode.js rename to ui/lib/replication/addon/controllers/replication-mode.js index b5b82ad762fa..17cc605a7a95 100644 --- a/ui/app/controllers/vault/cluster/replication/replication-mode.js +++ b/ui/lib/replication/addon/controllers/replication-mode.js @@ -5,4 +5,12 @@ import Controller from '@ember/controller'; export default Controller.extend({ rm: service('replication-mode'), replicationMode: alias('rm.mode'), + actions: { + onEnable(mode) { + return this.transitionToRoute('mode', mode); + }, + onDisable() { + return this.transitionToRoute('index'); + }, + }, }); diff --git a/ui/lib/replication/addon/engine.js b/ui/lib/replication/addon/engine.js new file mode 100644 index 000000000000..8529bf72913f --- /dev/null +++ b/ui/lib/replication/addon/engine.js @@ -0,0 +1,27 @@ +import Engine from 'ember-engines/engine'; +import loadInitializers from 'ember-load-initializers'; +import Resolver from './resolver'; +import config from './config/environment'; + +const { modulePrefix } = config; +/* eslint-disable ember/avoid-leaking-state-in-ember-objects */ +const Eng = Engine.extend({ + modulePrefix, + Resolver, + dependencies: { + services: [ + 'auth', + 'flash-messages', + 'namespace', + 'replication-mode', + 'router', + 'store', + 'version', + 'wizard', + ], + }, +}); + +loadInitializers(Eng, modulePrefix); + +export default Eng; diff --git a/ui/app/helpers/replication-action-for-mode.js b/ui/lib/replication/addon/helpers/replication-action-for-mode.js similarity index 100% rename from ui/app/helpers/replication-action-for-mode.js rename to ui/lib/replication/addon/helpers/replication-action-for-mode.js diff --git a/ui/app/mixins/replication-actions.js b/ui/lib/replication/addon/mixins/replication-actions.js similarity index 85% rename from ui/app/mixins/replication-actions.js rename to ui/lib/replication/addon/mixins/replication-actions.js index a2ab65237b9b..c09a60aa22d2 100644 --- a/ui/app/mixins/replication-actions.js +++ b/ui/lib/replication/addon/mixins/replication-actions.js @@ -8,6 +8,8 @@ export default Mixin.create({ store: service(), router: service(), loading: or('save.isRunning', 'submitSuccess.isRunning'), + onEnable() {}, + onDisable() {}, submitHandler(action, clusterMode, data, event) { let replicationMode = (data && data.replicationMode) || this.get('replicationMode'); if (event && event.preventDefault) { @@ -27,7 +29,7 @@ export default Mixin.create({ delete data.replicationMode; } - return this.get('save').perform(action, replicationMode, clusterMode, data); + return this.save.perform(action, replicationMode, clusterMode, data); }, save: task(function*(action, replicationMode, clusterMode, data) { @@ -39,7 +41,7 @@ export default Mixin.create({ } catch (e) { return this.submitError(e); } - yield this.get('submitSuccess').perform(resp, action, clusterMode); + yield this.submitSuccess.perform(resp, action, clusterMode); }).drop(), submitSuccess: task(function*(resp, action, mode) { @@ -61,7 +63,9 @@ export default Mixin.create({ }); return cluster; } - this.reset(); + if (this.reset) { + this.reset(); + } if (action === 'enable') { // do something to show model is pending cluster.set( @@ -76,22 +80,21 @@ export default Mixin.create({ store.unloadAll('secret-engine'); } } - const router = this.get('router'); - if (action === 'disable') { - yield router.transitionTo('vault.cluster.replication.mode', replicationMode); - } try { yield cluster.reload(); } catch (e) { // no error handling here } cluster.rollbackAttributes(); + if (action === 'disable') { + yield this.onDisable(); + } if (action === 'enable') { - yield router.transitionTo('vault.cluster.replication.mode', replicationMode); + yield this.onEnable(replicationMode); } if (mode === 'secondary' && replicationMode === 'dr') { - yield router.transitionTo('vault.cluster'); + yield this.router.transitionTo('vault.cluster'); } }).drop(), diff --git a/ui/lib/replication/addon/resolver.js b/ui/lib/replication/addon/resolver.js new file mode 100644 index 000000000000..2fb563d6c048 --- /dev/null +++ b/ui/lib/replication/addon/resolver.js @@ -0,0 +1,3 @@ +import Resolver from 'ember-resolver'; + +export default Resolver; diff --git a/ui/lib/replication/addon/routes.js b/ui/lib/replication/addon/routes.js new file mode 100644 index 000000000000..ff0212ea3dd6 --- /dev/null +++ b/ui/lib/replication/addon/routes.js @@ -0,0 +1,17 @@ +import buildRoutes from 'ember-engines/routes'; + +export default buildRoutes(function() { + this.route('index', { path: '/' }); + this.route('mode', { path: '/:replication_mode' }, function() { + //details + this.route('index', { path: '/' }); + this.route('manage'); + this.route('secondaries', function() { + this.route('add', { path: '/add' }); + this.route('revoke', { path: '/revoke' }); + this.route('config-show', { path: '/config/show/:secondary_id' }); + this.route('config-edit', { path: '/config/edit/:secondary_id' }); + this.route('config-create', { path: '/config/create/:secondary_id' }); + }); + }); +}); diff --git a/ui/app/routes/vault/cluster/replication.js b/ui/lib/replication/addon/routes/application.js similarity index 87% rename from ui/app/routes/vault/cluster/replication.js rename to ui/lib/replication/addon/routes/application.js index 900927c3ad86..dd9b3d5a3cc3 100644 --- a/ui/app/routes/vault/cluster/replication.js +++ b/ui/lib/replication/addon/routes/application.js @@ -6,6 +6,7 @@ import ClusterRoute from 'vault/mixins/cluster-route'; export default Route.extend(ClusterRoute, { version: service(), + store: service(), beforeModel() { return this.get('version') @@ -16,7 +17,7 @@ export default Route.extend(ClusterRoute, { }, model() { - return this.modelFor('vault.cluster'); + return this.store.findRecord('cluster', 'vault'); }, afterModel(model) { @@ -35,4 +36,9 @@ export default Route.extend(ClusterRoute, { return model; }); }, + actions: { + refresh() { + this.refresh(); + }, + }, }); diff --git a/ui/app/routes/vault/cluster/replication/index.js b/ui/lib/replication/addon/routes/index.js similarity index 81% rename from ui/app/routes/vault/cluster/replication/index.js rename to ui/lib/replication/addon/routes/index.js index 5aabd99f7b36..ca69628790bf 100644 --- a/ui/app/routes/vault/cluster/replication/index.js +++ b/ui/lib/replication/addon/routes/index.js @@ -7,6 +7,6 @@ export default Route.extend({ this.get('replicationMode').setMode(null); }, model() { - return this.modelFor('vault.cluster.replication'); + return this.modelFor('application'); }, }); diff --git a/ui/app/routes/vault/cluster/replication/mode.js b/ui/lib/replication/addon/routes/mode.js similarity index 58% rename from ui/app/routes/vault/cluster/replication/mode.js rename to ui/lib/replication/addon/routes/mode.js index 1494760c1f95..c996ec97ae40 100644 --- a/ui/app/routes/vault/cluster/replication/mode.js +++ b/ui/lib/replication/addon/routes/mode.js @@ -1,4 +1,3 @@ -import { on } from '@ember/object/evented'; import { inject as service } from '@ember/service'; import Route from '@ember/routing/route'; @@ -6,22 +5,16 @@ const SUPPORTED_REPLICATION_MODES = ['dr', 'performance']; export default Route.extend({ replicationMode: service(), - + store: service(), beforeModel() { const replicationMode = this.paramsFor(this.routeName).replication_mode; if (!SUPPORTED_REPLICATION_MODES.includes(replicationMode)) { - return this.transitionTo('vault.cluster.replication'); - } else { - return this._super(...arguments); + return this.transitionTo('index'); } }, - model() { - return this.modelFor('vault.cluster.replication'); - }, - - setReplicationMode: on('activate', 'enter', function() { const replicationMode = this.paramsFor(this.routeName).replication_mode; - this.get('replicationMode').setMode(replicationMode); - }), + this.replicationMode.setMode(replicationMode); + return this.modelFor('application'); + }, }); diff --git a/ui/lib/replication/addon/routes/mode/index.js b/ui/lib/replication/addon/routes/mode/index.js new file mode 100644 index 000000000000..8014ac517a00 --- /dev/null +++ b/ui/lib/replication/addon/routes/mode/index.js @@ -0,0 +1,7 @@ +import Route from '@ember/routing/route'; + +export default Route.extend({ + model() { + return this.modelFor('mode'); + }, +}); diff --git a/ui/app/routes/vault/cluster/replication/mode/manage.js b/ui/lib/replication/addon/routes/mode/manage.js similarity index 70% rename from ui/app/routes/vault/cluster/replication/mode/manage.js rename to ui/lib/replication/addon/routes/mode/manage.js index 9a30216d34b0..7f1a6dd4c33b 100644 --- a/ui/app/routes/vault/cluster/replication/mode/manage.js +++ b/ui/lib/replication/addon/routes/mode/manage.js @@ -2,7 +2,7 @@ import { camelize } from '@ember/string'; import { all } from 'rsvp'; import { inject as service } from '@ember/service'; import Route from '@ember/routing/route'; -import { replicationActionForMode } from 'vault/helpers/replication-action-for-mode'; +import { replicationActionForMode } from 'replication/helpers/replication-action-for-mode'; const pathForAction = (action, replicationMode, clusterMode) => { let path; @@ -18,9 +18,9 @@ export default Route.extend({ store: service(), model() { const store = this.get('store'); - const model = this.modelFor('vault.cluster.replication.mode'); + const model = this.modelFor('mode'); - const replicationMode = this.paramsFor('vault.cluster.replication.mode').replication_mode; + const replicationMode = this.paramsFor('mode').replication_mode; const clusterMode = model.get(replicationMode).get('modeForUrl'); const actions = replicationActionForMode([replicationMode, clusterMode]); return all( @@ -35,13 +35,13 @@ export default Route.extend({ }, beforeModel() { - const model = this.modelFor('vault.cluster.replication.mode'); - const replicationMode = this.paramsFor('vault.cluster.replication.mode').replication_mode; + const model = this.modelFor('mode'); + const replicationMode = this.paramsFor('mode').replication_mode; if ( model.get(replicationMode).get('replicationDisabled') || model.get(replicationMode).get('replicationUnsupported') ) { - return this.transitionTo('vault.cluster.replication.mode', replicationMode); + return this.transitionTo('mode', replicationMode); } }, }); diff --git a/ui/app/routes/vault/cluster/replication/mode/secondaries.js b/ui/lib/replication/addon/routes/mode/secondaries.js similarity index 73% rename from ui/app/routes/vault/cluster/replication/mode/secondaries.js rename to ui/lib/replication/addon/routes/mode/secondaries.js index d952f773b3c6..e3eac5187b5a 100644 --- a/ui/app/routes/vault/cluster/replication/mode/secondaries.js +++ b/ui/lib/replication/addon/routes/mode/secondaries.js @@ -1,13 +1,15 @@ import { setProperties } from '@ember/object'; import { hash } from 'rsvp'; import Route from '@ember/routing/route'; +import { inject as service } from '@ember/service'; export default Route.extend({ + store: service(), model() { - const replicationMode = this.paramsFor('vault.cluster.replication.mode').replication_mode; + const replicationMode = this.paramsFor('mode').replication_mode; return hash({ - cluster: this.modelFor('vault.cluster.replication.mode'), + cluster: this.modelFor('mode'), canAddSecondary: this.store .findRecord('capabilities', `sys/replication/${replicationMode}/primary/secondary-token`) .then(c => c.get('canUpdate')), @@ -23,13 +25,13 @@ export default Route.extend({ }); }, afterModel(model) { - const replicationMode = this.paramsFor('vault.cluster.replication.mode').replication_mode; + const replicationMode = this.paramsFor('mode').replication_mode; if ( !model.get(`${replicationMode}.isPrimary`) || model.get(`${replicationMode}.replicationDisabled`) || model.get(`${replicationMode}.replicationUnsupported`) ) { - return this.transitionTo('vault.cluster.replication.mode', replicationMode); + return this.transitionTo('mode', replicationMode); } }, }); diff --git a/ui/app/routes/vault/cluster/replication/mode/secondaries/add.js b/ui/lib/replication/addon/routes/mode/secondaries/add.js similarity index 67% rename from ui/app/routes/vault/cluster/replication/mode/secondaries/add.js rename to ui/lib/replication/addon/routes/mode/secondaries/add.js index 04843f225be1..0093867ecba9 100644 --- a/ui/app/routes/vault/cluster/replication/mode/secondaries/add.js +++ b/ui/lib/replication/addon/routes/mode/secondaries/add.js @@ -4,15 +4,15 @@ import Base from '../../replication-base'; export default Base.extend({ model() { return hash({ - cluster: this.modelFor('vault.cluster.replication.mode.secondaries'), + cluster: this.modelFor('mode.secondaries'), mounts: this.fetchMounts(), }); }, redirect(model) { - const replicationMode = this.get('replicationMode'); + const replicationMode = this.paramsFor('mode').replication_mode; if (!model.cluster.get(`${replicationMode}.isPrimary`) || !model.cluster.get('canAddSecondary')) { - return this.transitionTo('vault.cluster.replication.mode', model.cluster.get('name'), replicationMode); + return this.transitionTo('mode', replicationMode); } }, diff --git a/ui/app/routes/vault/cluster/replication/mode/secondaries/config-create.js b/ui/lib/replication/addon/routes/mode/secondaries/config-create.js similarity index 83% rename from ui/app/routes/vault/cluster/replication/mode/secondaries/config-create.js rename to ui/lib/replication/addon/routes/mode/secondaries/config-create.js index c39fe8b63d3f..8860c0b6c7ec 100644 --- a/ui/app/routes/vault/cluster/replication/mode/secondaries/config-create.js +++ b/ui/lib/replication/addon/routes/mode/secondaries/config-create.js @@ -13,7 +13,7 @@ export default Base.extend({ .findRecord('mount-filter-config', id) .then(() => { // if we find a record, transition to the edit view - return this.transitionTo('vault.cluster.replication.mode.secondaries.config-edit', id) + return this.transitionTo('mode.secondaries.config-edit', id) .followRedirects() .then(() => { flash.info( @@ -41,13 +41,13 @@ export default Base.extend({ !cluster.get(`${replicationMode}.isPrimary`) || !cluster.get('canAddSecondary') ) { - return this.transitionTo('vault.cluster.replication.mode', cluster.get('name'), replicationMode); + return this.transitionTo('mode', replicationMode); } }, model(params) { return hash({ - cluster: this.modelFor('vault.cluster.replication.mode'), + cluster: this.modelFor('mode'), config: this.findOrCreate(params.secondary_id), mounts: this.fetchMounts(), }); diff --git a/ui/app/routes/vault/cluster/replication/mode/secondaries/config-edit.js b/ui/lib/replication/addon/routes/mode/secondaries/config-edit.js similarity index 70% rename from ui/app/routes/vault/cluster/replication/mode/secondaries/config-edit.js rename to ui/lib/replication/addon/routes/mode/secondaries/config-edit.js index f2fd220c126f..172e058aa3fc 100644 --- a/ui/app/routes/vault/cluster/replication/mode/secondaries/config-edit.js +++ b/ui/lib/replication/addon/routes/mode/secondaries/config-edit.js @@ -6,7 +6,7 @@ export default Base.extend({ model(params) { return hash({ - cluster: this.modelFor('vault.cluster.replication.mode.secondaries'), + cluster: this.modelFor('mode.secondaries'), config: this.store.findRecord('mount-filter-config', params.secondary_id), mounts: this.fetchMounts(), }); @@ -14,14 +14,14 @@ export default Base.extend({ redirect(model) { const cluster = model.cluster; - const replicationMode = this.get('replicationMode'); + let replicationMode = this.paramsFor('mode').replication_mode; if ( !this.get('version.hasPerfReplication') || replicationMode !== 'performance' || !cluster.get(`${replicationMode}.isPrimary`) || !cluster.get('canAddSecondary') ) { - return this.transitionTo('vault.cluster.replication.mode', cluster.get('name'), replicationMode); + return this.transitionTo('mode', replicationMode); } }, }); diff --git a/ui/app/routes/vault/cluster/replication/mode/secondaries/config-show.js b/ui/lib/replication/addon/routes/mode/secondaries/config-show.js similarity index 73% rename from ui/app/routes/vault/cluster/replication/mode/secondaries/config-show.js rename to ui/lib/replication/addon/routes/mode/secondaries/config-show.js index de7b644d3fbd..fac0724ea4d1 100644 --- a/ui/app/routes/vault/cluster/replication/mode/secondaries/config-show.js +++ b/ui/lib/replication/addon/routes/mode/secondaries/config-show.js @@ -7,7 +7,7 @@ export default Base.extend({ model(params) { const id = params.secondary_id; return hash({ - cluster: this.modelFor('vault.cluster.replication'), + cluster: this.modelFor('application'), config: this.store.findRecord('mount-filter-config', id).catch(e => { if (e.httpStatus === 404) { // return an empty obj to let them nav to create @@ -20,13 +20,13 @@ export default Base.extend({ }, redirect(model) { const cluster = model.cluster; - const replicationMode = this.paramsFor('vault.cluster.replication.mode').replication_mode; + const replicationMode = this.paramsFor('mode').replication_mode; if ( !this.get('version.hasPerfReplication') || replicationMode !== 'performance' || !cluster.get(`${replicationMode}.isPrimary`) ) { - return this.transitionTo('vault.cluster.replication.mode', cluster.get('name'), replicationMode); + return this.transitionTo('mode', cluster.get('name'), replicationMode); } }, }); diff --git a/ui/app/routes/vault/cluster/replication/mode/secondaries/revoke.js b/ui/lib/replication/addon/routes/mode/secondaries/revoke.js similarity index 68% rename from ui/app/routes/vault/cluster/replication/mode/secondaries/revoke.js rename to ui/lib/replication/addon/routes/mode/secondaries/revoke.js index 041a5913f2a3..cc55822545d6 100644 --- a/ui/app/routes/vault/cluster/replication/mode/secondaries/revoke.js +++ b/ui/lib/replication/addon/routes/mode/secondaries/revoke.js @@ -2,13 +2,13 @@ import Base from '../../replication-base'; export default Base.extend({ model() { - return this.modelFor('vault.cluster.replication.mode.secondaries'); + return this.modelFor('mode.secondaries'); }, redirect(model) { const replicationMode = this.get('replicationMode'); if (!model.get(`${replicationMode}.isPrimary`) || !model.get('canRevokeSecondary')) { - return this.transitionTo('vault.cluster.replication', model.get('name')); + return this.transitionTo('index'); } }, diff --git a/ui/app/routes/vault/cluster/replication/replication-base.js b/ui/lib/replication/addon/routes/replication-base.js similarity index 97% rename from ui/app/routes/vault/cluster/replication/replication-base.js rename to ui/lib/replication/addon/routes/replication-base.js index f2cab56d76b3..f4ab308b25f8 100644 --- a/ui/app/routes/vault/cluster/replication/replication-base.js +++ b/ui/lib/replication/addon/routes/replication-base.js @@ -5,6 +5,9 @@ import Route from '@ember/routing/route'; import UnloadModelRouteMixin from 'vault/mixins/unload-model-route'; export default Route.extend(UnloadModelRouteMixin, { + store: service(), + version: service(), + rm: service('replication-mode'), modelPath: 'model.config', fetchMounts() { return hash({ @@ -15,7 +18,5 @@ export default Route.extend(UnloadModelRouteMixin, { }); }, - version: service(), - rm: service('replication-mode'), replicationMode: alias('rm.mode'), }); diff --git a/ui/lib/replication/addon/templates/application.hbs b/ui/lib/replication/addon/templates/application.hbs new file mode 100644 index 000000000000..e2147cab02d6 --- /dev/null +++ b/ui/lib/replication/addon/templates/application.hbs @@ -0,0 +1 @@ +{{outlet}} \ No newline at end of file diff --git a/ui/app/templates/components/mount-filter-config-list.hbs b/ui/lib/replication/addon/templates/components/mount-filter-config-list.hbs similarity index 92% rename from ui/app/templates/components/mount-filter-config-list.hbs rename to ui/lib/replication/addon/templates/components/mount-filter-config-list.hbs index ac64e5bf2411..6358319a3a29 100644 --- a/ui/app/templates/components/mount-filter-config-list.hbs +++ b/ui/lib/replication/addon/templates/components/mount-filter-config-list.hbs @@ -8,7 +8,7 @@ onchange={{action (mut config.mode) value="target.value"}} data-test-replication-filter-mount-mode=true > - {{#each (reduce-to-array "whitelist" "blacklist") as |mode|}} + {{#each (array "whitelist" "blacklist") as |mode|}} @@ -42,7 +42,7 @@
{{#each mounts as |mount|}} - {{#unless (or mount.local (includes singletonMountTypes mount.type))}} + {{#unless (or mount.local (contains mount.type singletonMountTypes))}} {{!-- auth mounts have apiPath, secret mounts use path --}} {{#with (or mount.apiPath mount.path) as |path| }}
+ {{#if (or (and (eq mode 'primary') cluster.canEnablePrimary) (and (eq mode 'secondary') cluster.canEnableSecondary))}} +
+
+ +
+
+ {{/if}} + +{{else if showModeSummary}} + + +

+ Replication +

+
+
+
+

+ {{!-- TODO convert to a new component that doesn't use partials + {{i-con class="has-text-grey is-medium" glyph="replication" size=20}} + --}} + Disaster Recovery (DR) +

+ {{#if cluster.dr.replicationEnabled}} + {{#link-to + "mode.index" + "dr" + class="link-plain" + }} + {{replication-mode-summary + mode="dr" + cluster=cluster + tagName="span" + }} + {{/link-to}} + {{else}} + {{replication-mode-summary + mode="dr" + cluster=cluster + tagName="div" + }} + {{/if}} +
+
+

+ {{!-- TODO convert to a new component that doesn't use partials + {{i-con class="has-text-grey is-medium" glyph="perf-replication" size=20}} + --}} + Performance +

+ {{#if cluster.dr.replicationEnabled}} + {{#link-to + "mode.index" + "performance" + class="link-plain" + }} + {{replication-mode-summary + mode="performance" + cluster=cluster + tagName="span" + }} + {{/link-to}} + {{else}} + {{replication-mode-summary + mode="performance" + cluster=cluster + tagName="div" + }} + {{/if}} +
+{{else}} + {{#if (eq replicationAttrs.mode 'initializing')}} + The cluster is initializing replication. This may take some time. + {{else}} + {{info-table-row label="Mode" value=replicationAttrs.mode}} + {{info-table-row label="Replication set" value=replicationAttrs.clusterId}} + {{info-table-row label="Secondary ID" value=replicationAttrs.secondaryId}} + {{info-table-row label="State" value=replicationAttrs.state}} + {{info-table-row label="Primary cluster address" value=replicationAttrs.primaryClusterAddr}} + {{info-table-row label="Replication state" value=replicationAttrs.replicationState}} + {{info-table-row label="Last WAL entry" value=replicationAttrs.lastWAL}} + {{info-table-row label="Last Remote WAL entry" value=replicationAttrs.lastRemoteWAL}} + {{info-table-row label="Merkle root index" value=replicationAttrs.merkleRoot}} + {{#if replicationAttrs.syncProgress}} + {{info-table-row label="Sync progress" value=(concat replicationAttrs.syncProgress.progress '/' replicationAttrs.syncProgress.total)}} + {{/if}} + {{/if}} +{{/if}} diff --git a/ui/app/templates/vault/cluster/replication/index.hbs b/ui/lib/replication/addon/templates/index.hbs similarity index 67% rename from ui/app/templates/vault/cluster/replication/index.hbs rename to ui/lib/replication/addon/templates/index.hbs index d6ca74b7af26..48ad8416e566 100644 --- a/ui/app/templates/vault/cluster/replication/index.hbs +++ b/ui/lib/replication/addon/templates/index.hbs @@ -10,8 +10,10 @@ @title="The current cluster configuration does not support replication" /> {{else}} - {{replication-summary - cluster=model - showModeSummary=true - }} + {{/if}} diff --git a/ui/app/templates/vault/cluster/replication/mode.hbs b/ui/lib/replication/addon/templates/mode.hbs similarity index 80% rename from ui/app/templates/vault/cluster/replication/mode.hbs rename to ui/lib/replication/addon/templates/mode.hbs index ec56266bb23a..57e69271f2b9 100644 --- a/ui/app/templates/vault/cluster/replication/mode.hbs +++ b/ui/lib/replication/addon/templates/mode.hbs @@ -29,18 +29,18 @@
- {{#link-to "vault.cluster.replication.mode.secondaries" model.name replicationMode class="button"}} + {{#link-to "mode.secondaries" replicationMode class="button"}} Cancel {{/link-to}}
diff --git a/ui/app/templates/vault/cluster/replication/mode/secondaries/config-create.hbs b/ui/lib/replication/addon/templates/mode/secondaries/config-create.hbs similarity index 91% rename from ui/app/templates/vault/cluster/replication/mode/secondaries/config-create.hbs rename to ui/lib/replication/addon/templates/mode/secondaries/config-create.hbs index b168a4934947..ae92beb756c0 100644 --- a/ui/app/templates/vault/cluster/replication/mode/secondaries/config-create.hbs +++ b/ui/lib/replication/addon/templates/mode/secondaries/config-create.hbs @@ -16,7 +16,7 @@
{{#link-to - "vault.cluster.replication.mode.secondaries.config-show" + "mode.secondaries.config-show" model.config.id class="button" }} diff --git a/ui/app/templates/vault/cluster/replication/mode/secondaries/config-edit.hbs b/ui/lib/replication/addon/templates/mode/secondaries/config-edit.hbs similarity index 94% rename from ui/app/templates/vault/cluster/replication/mode/secondaries/config-edit.hbs rename to ui/lib/replication/addon/templates/mode/secondaries/config-edit.hbs index f5c1085bab2a..65382fb29ae6 100644 --- a/ui/app/templates/vault/cluster/replication/mode/secondaries/config-edit.hbs +++ b/ui/lib/replication/addon/templates/mode/secondaries/config-edit.hbs @@ -17,7 +17,7 @@
{{#link-to - "vault.cluster.replication.mode.secondaries.config-show" + "mode.secondaries.config-show" model.config.id class="button" }} diff --git a/ui/app/templates/vault/cluster/replication/mode/secondaries/config-show.hbs b/ui/lib/replication/addon/templates/mode/secondaries/config-show.hbs similarity index 90% rename from ui/app/templates/vault/cluster/replication/mode/secondaries/config-show.hbs rename to ui/lib/replication/addon/templates/mode/secondaries/config-show.hbs index 9e65248518a1..319057260c08 100644 --- a/ui/app/templates/vault/cluster/replication/mode/secondaries/config-show.hbs +++ b/ui/lib/replication/addon/templates/mode/secondaries/config-show.hbs @@ -25,7 +25,7 @@ {{#if model.config.mode}}
{{#link-to - 'vault.cluster.replication.mode.secondaries.config-edit' + "mode.secondaries.config-edit" model.config.id class="button" data-test-replication-link="edit-mount-config" @@ -36,7 +36,7 @@ {{else}}
{{#link-to - 'vault.cluster.replication.mode.secondaries.config-create' + "mode.secondaries.config-create" model.config.id class="button" data-test-replication-link="create-mount-config" diff --git a/ui/app/templates/vault/cluster/replication/mode/secondaries/index.hbs b/ui/lib/replication/addon/templates/mode/secondaries/index.hbs similarity index 84% rename from ui/app/templates/vault/cluster/replication/mode/secondaries/index.hbs rename to ui/lib/replication/addon/templates/mode/secondaries/index.hbs index a5035c21d922..1530287ffa3d 100644 --- a/ui/app/templates/vault/cluster/replication/mode/secondaries/index.hbs +++ b/ui/lib/replication/addon/templates/mode/secondaries/index.hbs @@ -31,7 +31,7 @@ {{/if}} {{#if (eq replicationMode 'performance')}}
  • - {{#link-to "vault.cluster.replication.mode.secondaries.config-show" model.name replicationMode secondary data-test-replication-mount-filter-link=true}} + {{#link-to "mode.secondaries.config-show" replicationMode secondary data-test-replication-mount-filter-link=true}} Mount filter config {{/link-to}}
  • @@ -51,7 +51,7 @@ @message="Associated secondary clusters will be listed here. Add your first secondary cluster to get started." > {{#if model.canAddSecondary}} - {{#link-to 'vault.cluster.replication.mode.secondaries.add' model.name replicationMode class="link" }} + {{#link-to "mode.secondaries.add" replicationMode class="link" }} Add secondary {{/link-to}} {{/if}} @@ -63,14 +63,14 @@
    {{#if model.canAddSecondary}}
    - {{#link-to 'vault.cluster.replication.mode.secondaries.add' model.name replicationMode class="button" data-test-secondary-add=true }} + {{#link-to "mode.secondaries.add" replicationMode class="button" data-test-secondary-add=true }} Add {{/link-to}}
    {{/if}} {{#if model.canRevokeSecondary}}
    - {{#link-to 'vault.cluster.replication.mode.secondaries.revoke' model.name replicationMode class="button"}} + {{#link-to "mode.secondaries.revoke" replicationMode class="button"}} Revoke {{/link-to}}
    diff --git a/ui/app/templates/vault/cluster/replication/mode/secondaries/revoke.hbs b/ui/lib/replication/addon/templates/mode/secondaries/revoke.hbs similarity index 91% rename from ui/app/templates/vault/cluster/replication/mode/secondaries/revoke.hbs rename to ui/lib/replication/addon/templates/mode/secondaries/revoke.hbs index b44ce837b9c2..2214a7b6531d 100644 --- a/ui/app/templates/vault/cluster/replication/mode/secondaries/revoke.hbs +++ b/ui/lib/replication/addon/templates/mode/secondaries/revoke.hbs @@ -32,7 +32,7 @@
    {{#unless isRevoking}} - {{#link-to "vault.cluster.replication.mode.secondaries" model.name replicationMode class="button"}} + {{#link-to "mode.secondaries" replicationMode class="button"}} Cancel {{/link-to}} {{/unless}} diff --git a/ui/app/utils/decode-config-from-jwt.js b/ui/lib/replication/addon/utils/decode-config-from-jwt.js similarity index 93% rename from ui/app/utils/decode-config-from-jwt.js rename to ui/lib/replication/addon/utils/decode-config-from-jwt.js index d0c840621df3..66e541f2a83e 100644 --- a/ui/app/utils/decode-config-from-jwt.js +++ b/ui/lib/replication/addon/utils/decode-config-from-jwt.js @@ -1,4 +1,4 @@ -import { decodeString } from 'vault/utils/b64'; +import { decodeString } from 'core/utils/b64'; /* * @param token - Replication Secondary Activation Token diff --git a/ui/lib/replication/config/environment.js b/ui/lib/replication/config/environment.js new file mode 100644 index 000000000000..966d9dd134c5 --- /dev/null +++ b/ui/lib/replication/config/environment.js @@ -0,0 +1,11 @@ +/* eslint-env node */ +'use strict'; + +module.exports = function(environment) { + let ENV = { + modulePrefix: 'replication', + environment, + }; + + return ENV; +}; diff --git a/ui/lib/replication/index.js b/ui/lib/replication/index.js new file mode 100644 index 000000000000..5df8f8b602c1 --- /dev/null +++ b/ui/lib/replication/index.js @@ -0,0 +1,17 @@ +/* eslint-env node */ +/* eslint-disable ember/avoid-leaking-state-in-ember-objects */ +'use strict'; + +const EngineAddon = require('ember-engines/lib/engine-addon'); + +module.exports = EngineAddon.extend({ + name: 'replication', + + lazyLoading: { + enabled: true, + }, + + isDevelopingAddon() { + return true; + }, +}); diff --git a/ui/lib/replication/package.json b/ui/lib/replication/package.json new file mode 100644 index 000000000000..108f8834884a --- /dev/null +++ b/ui/lib/replication/package.json @@ -0,0 +1,16 @@ +{ + "name": "replication", + "keywords": [ + "ember-addon", + "ember-engine" + ], + "dependencies": { + "ember-cli-htmlbars": "*", + "ember-cli-babel": "*" + }, + "ember-addon": { + "paths": [ + "../core" + ] + } +} diff --git a/ui/package.json b/ui/package.json index c85ff4f7bf23..f353986f0fd9 100644 --- a/ui/package.json +++ b/ui/package.json @@ -85,6 +85,7 @@ "ember-copy": "^1.0.0", "ember-data": "~3.4.0", "ember-data-model-fragments": "^3.3.0", + "ember-engines": "^0.7.0", "ember-export-application-global": "^2.0.0", "ember-fetch": "^6.1.0", "ember-inflector": "^3.0.0", @@ -132,19 +133,21 @@ "@storybook/addon-viewport": "^5.0.5", "@storybook/addons": "^5.0.5", "@storybook/ember": "^5.0.5", - "@storybook/ember-cli-storybook": "meirish/ember-cli-storybook", + "@storybook/ember-cli-storybook": "meirish/ember-cli-storybook#6bd58326d8c21e986d390b541ae5e49089d61b93", "babel-loader": "^8.0.5", "husky": "^1.1.3", "jsdoc-to-markdown": "^4.0.1", "lint-staged": "^8.0.4" }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": " >= 10.*" }, "private": true, "ember-addon": { "paths": [ - "lib/css" + "lib/core", + "lib/css", + "lib/replication" ] }, "husky": { diff --git a/ui/scripts/gen-story-md.js b/ui/scripts/gen-story-md.js index e8559f8b379f..c50454cc8165 100644 --- a/ui/scripts/gen-story-md.js +++ b/ui/scripts/gen-story-md.js @@ -4,7 +4,10 @@ const fs = require('fs'); const jsdoc2md = require('jsdoc-to-markdown'); var args = process.argv.slice(2); const name = args[0]; -const inputFile = `app/components/${name}.js`; +const addonOrEngine = args[1]; +const inputFile = addonOrEngine + ? `lib/${addonOrEngine}/addon/components/${name}.js` + : `app/components/${name}.js`; const outputFile = `stories/${name}.md`; const component = name .split('-') @@ -20,7 +23,7 @@ const pageBreakIndex = md.lastIndexOf('---'); //this is our last page break const seeLinks = `**See** -- [Uses of ${component}](https://github.com/hashicorp/vault/search?l=Handlebars&q=${component}) +- [Uses of ${component}](https://github.com/hashicorp/vault/search?l=Handlebars&q=${component}+OR+${name}) - [${component} Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/${name}.js) `; diff --git a/ui/stories/alert-banner.stories.js b/ui/stories/alert-banner.stories.js index 482a9de2db8f..eff1527afc7b 100644 --- a/ui/stories/alert-banner.stories.js +++ b/ui/stories/alert-banner.stories.js @@ -2,7 +2,8 @@ import hbs from 'htmlbars-inline-precompile'; import { storiesOf } from '@storybook/ember'; import notes from './alert-banner.md'; -import { MESSAGE_TYPES } from '../app/helpers/message-types.js'; +import { MESSAGE_TYPES } from '../lib/core/addon/helpers/message-types.js'; + storiesOf('Alerts/AlertBanner/', module) .addParameters({ options: { showPanel: false } }) diff --git a/ui/stories/alert-inline.stories.js b/ui/stories/alert-inline.stories.js index 0ecd8ed7e605..5dbac286a9bb 100644 --- a/ui/stories/alert-inline.stories.js +++ b/ui/stories/alert-inline.stories.js @@ -2,7 +2,7 @@ import hbs from 'htmlbars-inline-precompile'; import { storiesOf } from '@storybook/ember'; import notes from './alert-inline.md'; -import { MESSAGE_TYPES } from '../app/helpers/message-types.js'; +import { MESSAGE_TYPES } from '../lib/core/addon/helpers/message-types.js'; storiesOf('Alerts/AlertInline/', module) .addParameters({ options: { showPanel: false } }) diff --git a/ui/stories/alert-popup.stories.js b/ui/stories/alert-popup.stories.js index c32d4e66ba36..ba5410e99b09 100644 --- a/ui/stories/alert-popup.stories.js +++ b/ui/stories/alert-popup.stories.js @@ -2,7 +2,7 @@ import hbs from 'htmlbars-inline-precompile'; import { storiesOf } from '@storybook/ember'; import notes from './alert-popup.md'; -import { MESSAGE_TYPES } from '../app/helpers/message-types.js'; +import { MESSAGE_TYPES } from '../lib/core/addon/helpers/message-types.js'; storiesOf('Alerts/AlertPopup/', module) .addParameters({ options: { showPanel: false } }) diff --git a/ui/stories/doc-link.md b/ui/stories/doc-link.md new file mode 100644 index 000000000000..3bf00513e2f2 --- /dev/null +++ b/ui/stories/doc-link.md @@ -0,0 +1,22 @@ + + +## DocLink +`DocLink` components are used to render anchor links to relevant Vault documentation. + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| path | String | "/" | The path to documentation on vaultproject.io that the component should link to. | + +**Example** + +```js + Learn about KV v2 +``` + +**See** + +- [Uses of DocLink](https://github.com/hashicorp/vault/search?l=Handlebars&q=DocLink) +- [DocLink Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/doc-link.js) + +--- diff --git a/ui/stories/doc-link.stories.js b/ui/stories/doc-link.stories.js new file mode 100644 index 000000000000..40a8a5eab485 --- /dev/null +++ b/ui/stories/doc-link.stories.js @@ -0,0 +1,16 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import notes from './doc-link.md'; + + +storiesOf('DocLink/', module) + .addParameters({ options: { showPanel: true } }) + .add(`DocLink`, () => ({ + template: hbs` +
    Doc Link
    + Learn about KV v2 + ` + }), + {notes} +); diff --git a/ui/stories/empty-state.md b/ui/stories/empty-state.md new file mode 100644 index 000000000000..b0534c87a28f --- /dev/null +++ b/ui/stories/empty-state.md @@ -0,0 +1,24 @@ + + +## EmptyState +`EmptyState` components are used to render a helpful message and any necessary content when a user +encounters a state that would usually be blank. + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| title | String | | A short label for the empty state | +| message | String | | A description of why a user might be seeing the empty state and possibly instructions for actions they may take. | + +**Example** + +```js + +``` + +**See** + +- [Uses of EmptyState](https://github.com/hashicorp/vault/search?l=Handlebars&q=EmptyState) +- [EmptyState Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/empty-state.js) + +--- diff --git a/ui/stories/empty-state.stories.js b/ui/stories/empty-state.stories.js new file mode 100644 index 000000000000..3d84cb810276 --- /dev/null +++ b/ui/stories/empty-state.stories.js @@ -0,0 +1,35 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import { withKnobs, text } from '@storybook/addon-knobs'; +import notes from './empty-state.md'; + +storiesOf('EmptyState/', module) + .addParameters({ options: { showPanel: true } }) + .addDecorator(withKnobs({escapeHTML: false})) + .add(`EmptyState`, () => ({ + template: hbs` +
    Empty State
    + + `, + context: { + title: text('Title', 'You don\'t have an secrets yet'), + message: text('Message', 'An explanation of why you don\'t have any secrets but also you maybe want to create one.') + }, + }), + {notes} + ) + .add(`EmptyState with content block`, () => ({ + template: hbs` +
    Empty State
    + + Learn about KV v2 + + `, + context: { + title: text('Title', 'You don\'t have an secrets yet'), + message: text('Message', 'An explanation of why you don\'t have any secrets but also you maybe want to create one.') + }, + }), + {notes} + ); diff --git a/ui/stories/info-table-row.md b/ui/stories/info-table-row.md new file mode 100644 index 000000000000..a3d7f28ab3d4 --- /dev/null +++ b/ui/stories/info-table-row.md @@ -0,0 +1,25 @@ + + +## InfoTableRow +`InfoTableRow` displays a label and a value in a table-row style manner. The component is responsive so +that the value breaks under the label on smaller viewports. + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| value | any | | The the data to be displayed - by default the content of the component will only show if there is a value. Also note that special handling is given to boolean values - they will render `Yes` for true and `No` for false. | +| label | string | null | The display name for the value. | +| alwaysRender | Boolean | false | Indicates if the component content should be always be rendered. When false, the value of `value` will be used to determine if the component should render. | + +**Example** + +```js + +``` + +**See** + +- [Uses of InfoTableRow](https://github.com/hashicorp/vault/search?l=Handlebars&q=InfoTableRow+OR+info-table-row) +- [InfoTableRow Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/info-table-row.js) + +--- diff --git a/ui/stories/info-table-row.stories.js b/ui/stories/info-table-row.stories.js new file mode 100644 index 000000000000..afa44f37d9ef --- /dev/null +++ b/ui/stories/info-table-row.stories.js @@ -0,0 +1,36 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import { withKnobs, boolean, text } from '@storybook/addon-knobs'; +import notes from './info-table-row.md'; + + +storiesOf('InfoTableRow/', module) + .addParameters({ options: { showPanel: true } }) + .addDecorator(withKnobs({escapeHTML: false})) + .add(`InfoTableRow with text value`, () => ({ + template: hbs` +
    Info Table Row
    + + `, + context: { + label: text('Label', 'TTL'), + value: text('Value', '30m'), + alwaysRender: boolean('Always render?', false), + }, + }), + {notes} + ) + .add(`InfoTableRow with boolean value`, () => ({ + template: hbs` +
    Info Table Row
    + + `, + context: { + label: 'Local mount?', + value: boolean('Value', true), + alwaysRender: boolean('Always render?', true), + }, + }), + {notes} +); diff --git a/ui/stories/layout-loading.md b/ui/stories/layout-loading.md new file mode 100644 index 000000000000..83bca284162a --- /dev/null +++ b/ui/stories/layout-loading.md @@ -0,0 +1,17 @@ + + +## LayoutLoading +`LayoutLoading` displays the `VaultLogoSpinner` component in a centered full-page layout. + +**Example** + +```js + +``` + +**See** + +- [Uses of LayoutLoading](https://github.com/hashicorp/vault/search?l=Handlebars&q=LayoutLoading) +- [LayoutLoading Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/layout-loading.js) + +--- diff --git a/ui/stories/layout-loading.stories.js b/ui/stories/layout-loading.stories.js new file mode 100644 index 000000000000..0b8e268fbf7e --- /dev/null +++ b/ui/stories/layout-loading.stories.js @@ -0,0 +1,16 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import notes from './layout-loading.md'; + +storiesOf('Loading/LayoutLoading/', module) + .addParameters({ options: { showPanel: true } }) + .add(`LayoutLoading`, () => ({ + template: hbs` +
    Layout Loading
    + + `, + context: {}, + }), + {notes} +); diff --git a/ui/stories/message-error.md b/ui/stories/message-error.md new file mode 100644 index 000000000000..af6d541b4b34 --- /dev/null +++ b/ui/stories/message-error.md @@ -0,0 +1,24 @@ + + +## MessageError +`MessageError` extracts an error from a model or a passed error and displays it using the `AlertBanner` component. + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| model | DS.Model | | An Ember data model that will be used to bind error statest to the internal `errors` property. | +| errors | Array | | An array of error strings to show. | +| errorMessage | String | | An Error string to display. | + +**Example** + +```js + +``` + +**See** + +- [Uses of MessageError](https://github.com/hashicorp/vault/search?l=Handlebars&q=MessageError) +- [MessageError Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/message-error.js) + +--- diff --git a/ui/stories/message-error.stories.js b/ui/stories/message-error.stories.js new file mode 100644 index 000000000000..351f2f95794c --- /dev/null +++ b/ui/stories/message-error.stories.js @@ -0,0 +1,25 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import notes from './message-error.md'; + +let model = Ember.Object.create({ + adapterError: { + message: 'This is an adapterError on the model' + }, + isError: true +}); + +storiesOf('MessageError/', module) + .addParameters({ options: { showPanel: true } }) + .add(`MessageError`, () => ({ + template: hbs` +
    Message Error
    + + `, + context: { + model + } + }), + {notes} +); diff --git a/ui/stories/popup-menu.md b/ui/stories/popup-menu.md new file mode 100644 index 000000000000..dee242a7ddb2 --- /dev/null +++ b/ui/stories/popup-menu.md @@ -0,0 +1,23 @@ + + +## PopupMenu +`PopupMenu` displays a button that when pressed will toggle open a menu that is yielded in the content +block. + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| contentClass | String | '' | A class that will be applied to the yielded content of the popup. | + +**Example** + +```js + +``` + +**See** + +- [Uses of PopupMenu](https://github.com/hashicorp/vault/search?l=Handlebars&q=PopupMenu) +- [PopupMenu Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/popup-menu.js) + +--- diff --git a/ui/stories/popup-menu.stories.js b/ui/stories/popup-menu.stories.js new file mode 100644 index 000000000000..520ec3c730ed --- /dev/null +++ b/ui/stories/popup-menu.stories.js @@ -0,0 +1,17 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import notes from './popup-menu.md'; + + +storiesOf('PopupMenu/', module) + .addParameters({ options: { showPanel: true } }) + .add(`PopupMenu`, () => ({ + template: hbs` +
    Popup Menu
    + + `, + context: {}, + }), + {notes} +); diff --git a/ui/stories/ttl-picker.md b/ui/stories/ttl-picker.md new file mode 100644 index 000000000000..c7671b6e07b1 --- /dev/null +++ b/ui/stories/ttl-picker.md @@ -0,0 +1,27 @@ + + +## TtlPicker +`TtlPicker` components are used to expand and collapse content with a toggle. + + +| Param | Type | Default | Description | +| --- | --- | --- | --- | +| labelClass | String | "" | A CSS class to add to the label. | +| labelText | String | "TTL" | The text content of the label associated with the widget. | +| initialValue | Number | | The starting value of the TTL; | +| setDefaultValue | Boolean | true | If true, the component will trigger onChange on the initial render, causing a value to be set. | +| onChange | function | Function.prototype | The function to call when the value of the ttl changes. | +| outputSeconds | Boolean | false | If true, the component will trigger onChange with a value converted to seconds instead of a Golang duration string. | + +**Example** + +```js + +``` + +**See** + +- [Uses of TtlPicker](https://github.com/hashicorp/vault/search?l=Handlebars&q=TtlPicker) +- [TtlPicker Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/ttl-picker.js) + +--- diff --git a/ui/stories/ttl-picker.stories.js b/ui/stories/ttl-picker.stories.js new file mode 100644 index 000000000000..019d61a6cfa4 --- /dev/null +++ b/ui/stories/ttl-picker.stories.js @@ -0,0 +1,16 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import notes from './ttl-picker.md'; + + +storiesOf('TtlPicker/', module) + .addParameters({ options: { showPanel: false } }) + .add(`TtlPicker`, () => ({ + template: hbs` +
    Ttl Picker
    + + `, + }), + {notes} +); diff --git a/ui/stories/vault-logo-spinner.md b/ui/stories/vault-logo-spinner.md new file mode 100644 index 000000000000..c392d4c0fa86 --- /dev/null +++ b/ui/stories/vault-logo-spinner.md @@ -0,0 +1,17 @@ + + +## VaultLogoSpinner +`VaultLogoSpinner` displays an animated Vault logo to use for loading screens. + +**Example** + +```js + +``` + +**See** + +- [Uses of VaultLogoSpinner](https://github.com/hashicorp/vault/search?l=Handlebars&q=VaultLogoSpinner) +- [VaultLogoSpinner Source Code](https://github.com/hashicorp/vault/blob/master/ui/app/components/vault-logo-spinner.js) + +--- diff --git a/ui/stories/vault-logo-spinner.stories.js b/ui/stories/vault-logo-spinner.stories.js new file mode 100644 index 000000000000..0cb90ab1f472 --- /dev/null +++ b/ui/stories/vault-logo-spinner.stories.js @@ -0,0 +1,17 @@ +/* eslint-disable import/extensions */ +import hbs from 'htmlbars-inline-precompile'; +import { storiesOf } from '@storybook/ember'; +import notes from './vault-logo-spinner.md'; + + +storiesOf('Loading/VaultLogoSpinner/', module) + .addParameters({ options: { showPanel: true } }) + .add(`VaultLogoSpinner`, () => ({ + template: hbs` +
    Vault Logo Spinner
    + + `, + context: {}, + }), + {notes} +); diff --git a/ui/tests/acceptance/enterprise-replication-test.js b/ui/tests/acceptance/enterprise-replication-test.js index 5dc4b59624c7..6cf83fe9369a 100644 --- a/ui/tests/acceptance/enterprise-replication-test.js +++ b/ui/tests/acceptance/enterprise-replication-test.js @@ -15,7 +15,7 @@ const disableReplication = async (type, assert) => { await click('[data-test-disable-replication] button'); await click('[data-test-confirm-button]'); if (assert) { - assert.equal(currentURL(), `/vault/replication/${type}`, 'redirects to the replication page'); + assert.equal(currentURL(), `/vault/replication`, 'redirects to the replication page'); assert.equal( flash.latestMessage, 'This cluster is having replication disabled. Vault will be unavailable for a brief period and will resume service shortly.', @@ -32,12 +32,12 @@ module('Acceptance | Enterprise | replication', function(hooks) { hooks.beforeEach(async function() { await authPage.login(); await disableReplication('dr'); - return disableReplication('performance'); + await disableReplication('performance'); }); hooks.afterEach(async function() { await disableReplication('dr'); - return disableReplication('performance'); + await disableReplication('performance'); }); test('replication', async function(assert) { @@ -139,7 +139,7 @@ module('Acceptance | Enterprise | replication', function(hooks) { await click('[data-test-replication-link="secondaries"]'); assert .dom('[data-test-secondary-name]') - .hasText(secondaryName, 'it displays the secondary in the list of known secondaries'); + .includesText(secondaryName, 'it displays the secondary in the list of known secondaries'); }); test('disabling dr primary when perf replication is enabled', async function(assert) { diff --git a/ui/tests/integration/components/mount-filter-config-list-test.js b/ui/tests/integration/components/mount-filter-config-list-test.js index 1afd600dee2c..2ce407054b2d 100644 --- a/ui/tests/integration/components/mount-filter-config-list-test.js +++ b/ui/tests/integration/components/mount-filter-config-list-test.js @@ -2,9 +2,11 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { render, click, findAll, fillIn, blur } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; +import engineResolverFor from 'ember-engines/test-support/engine-resolver-for'; +const resolver = engineResolverFor('replication'); module('Integration | Component | mount filter config list', function(hooks) { - setupRenderingTest(hooks); + setupRenderingTest(hooks, { resolver }); test('it renders', async function(assert) { this.set('config', { mode: 'whitelist', paths: [] }); diff --git a/ui/tests/integration/components/replication-actions-test.js b/ui/tests/integration/components/replication-actions-test.js index 9773c856c4e8..9fe7a194fd4d 100644 --- a/ui/tests/integration/components/replication-actions-test.js +++ b/ui/tests/integration/components/replication-actions-test.js @@ -4,9 +4,14 @@ import Service from '@ember/service'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { click, fillIn, blur, render, find } from '@ember/test-helpers'; +import { camelize } from '@ember/string'; +import engineResolverFor from 'ember-engines/test-support/engine-resolver-for'; + import hbs from 'htmlbars-inline-precompile'; import sinon from 'sinon'; +const resolver = engineResolverFor('replication'); + const storeStub = Service.extend({ callArgs: null, adapterFor() { @@ -27,7 +32,7 @@ const routerService = Service.extend({ }); module('Integration | Component | replication actions', function(hooks) { - setupRenderingTest(hooks); + setupRenderingTest(hooks, { resolver }); hooks.beforeEach(function() { run(() => { @@ -94,6 +99,7 @@ module('Integration | Component | replication actions', function(hooks) { mode: clusterMode, modeForUrl: clusterMode, }, + [`can${camelize(action)}`]: true, reload() { return resolve(); }, @@ -114,11 +120,7 @@ module('Integration | Component | replication actions', function(hooks) { hbs`{{replication-actions model=model replicationMode=replicationMode selectedAction=selectedAction onSubmit=(action onSubmit)}}` ); - assert.equal( - find('h4').textContent.trim(), - headerText, - `${testKey}: renders the correct partial as default` - ); + assert.equal(find('h4').textContent.trim(), headerText, `${testKey}: renders the correct component`); if (typeof fillInFn === 'function') { await fillInFn.call(this); diff --git a/ui/tests/test-helper.js b/ui/tests/test-helper.js index 758d65a667ae..6983e85b6234 100644 --- a/ui/tests/test-helper.js +++ b/ui/tests/test-helper.js @@ -3,9 +3,12 @@ import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; import './helpers/flash-message'; +import preloadAssets from 'ember-asset-loader/test-support/preload-assets'; +import manifest from 'vault/config/asset-manifest'; -setApplication(Application.create(config.APP)); - -start({ - setupTestIsolationValidation: true, +preloadAssets(manifest).then(() => { + setApplication(Application.create(config.APP)); + start({ + setupTestIsolationValidation: true, + }); }); diff --git a/ui/tests/unit/utils/decode-config-from-jwt-test.js b/ui/tests/unit/utils/decode-config-from-jwt-test.js index 2b1f4884842d..e39cdfe099e9 100644 --- a/ui/tests/unit/utils/decode-config-from-jwt-test.js +++ b/ui/tests/unit/utils/decode-config-from-jwt-test.js @@ -1,4 +1,4 @@ -import decodeConfigFromJWT from 'vault/utils/decode-config-from-jwt'; +import decodeConfigFromJWT from 'replication/utils/decode-config-from-jwt'; import { module, test } from 'qunit'; module('Unit | Util | decode config from jwt', function() { diff --git a/ui/yarn.lock b/ui/yarn.lock index ce12090c9cb3..b641e596d1e1 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -1815,9 +1815,9 @@ webpack-dev-middleware "^3.5.1" webpack-hot-middleware "^2.24.3" -"@storybook/ember-cli-storybook@meirish/ember-cli-storybook": +"@storybook/ember-cli-storybook@meirish/ember-cli-storybook#6bd58326d8c21e986d390b541ae5e49089d61b93": version "0.1.0" - resolved "https://codeload.github.com/meirish/ember-cli-storybook/tar.gz/f4e63a0cc9ba8e3b7f8865b8632abbff67ec42a4" + resolved "https://codeload.github.com/meirish/ember-cli-storybook/tar.gz/6bd58326d8c21e986d390b541ae5e49089d61b93" dependencies: cheerio "^1.0.0-rc.2" ember-cli-babel "^7.1.2" @@ -1980,6 +1980,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== +"@types/tmp@^0.0.33": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/tmp/-/tmp-0.0.33.tgz#1073c4bc824754ae3d10cfab88ab0237ba964e4d" + integrity sha1-EHPEvIJHVK49EM+riKsCN7qWTk0= + "@webassemblyjs/ast@1.5.13": version "1.5.13" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.5.13.tgz#81155a570bd5803a30ec31436bc2c9c0ede38f25" @@ -2362,6 +2367,11 @@ acorn@^5.0.0, acorn@^5.5.0, acorn@^5.5.3, acorn@^5.6.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.2.tgz#91fa871883485d06708800318404e72bfb26dcc5" integrity sha512-cJrKCNcr2kv8dlDnbw+JPUGjHZzo4myaxOLmpOX8a+rgX94YeTcTMv/LFJUSByRpc+i4GgVnnhLxvMu/2Y+rqw== +acorn@^5.1.1: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + acorn@^6.0.5, acorn@^6.0.7: version "6.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" @@ -2472,7 +2482,7 @@ amd-name-resolver@1.2.0, amd-name-resolver@^1.2.0: dependencies: ensure-posix-path "^1.0.1" -amd-name-resolver@^1.2.1: +amd-name-resolver@1.3.1, amd-name-resolver@^1.2.1: version "1.3.1" resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-1.3.1.tgz#ffe71c683c6e7191fc4ae1bb3aaed15abea135d9" integrity sha512-26qTEWqZQ+cxSYygZ4Cf8tsjDBLceJahhtewxtKZA3SRa4PluuqYCuheemDQD+7Mf5B7sr+zhTDWAHDh02a1Dw== @@ -2480,6 +2490,13 @@ amd-name-resolver@^1.2.1: ensure-posix-path "^1.0.1" object-hash "^1.3.1" +amd-name-resolver@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-0.0.6.tgz#d3e4ba2dfcaab1d820c1be9de947c67828cfe595" + integrity sha1-0+S6Lfyqsdggwb6d6UfGeCjP5ZU= + 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" @@ -3184,6 +3201,11 @@ babel-plugin-check-es2015-constants@^6.22.0: dependencies: babel-runtime "^6.22.0" +babel-plugin-compact-reexports@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-compact-reexports/-/babel-plugin-compact-reexports-1.1.0.tgz#d329cf70ff882e1b3c916da15b312338caf29490" + integrity sha512-+KgjNJ5yMeZzJxYZdLEy9m82m92aL7FLvNJcK6dYJbW06t+UTpFJ2FVSs35zMfURcPnrQELYhLG4VC+kt/4gvw== + babel-plugin-debug-macros@^0.1.10, babel-plugin-debug-macros@^0.1.11: version "0.1.11" resolved "https://registry.yarnpkg.com/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.1.11.tgz#6c562bf561fccd406ce14ab04f42c218cf956605" @@ -4278,7 +4300,7 @@ broccoli-clean-css@^1.1.0: inline-source-map-comment "^1.0.5" json-stable-stringify "^1.0.0" -broccoli-concat@^3.2.2: +broccoli-concat@^3.2.2, broccoli-concat@^3.7.3: version "3.7.3" resolved "https://registry.yarnpkg.com/broccoli-concat/-/broccoli-concat-3.7.3.tgz#0dca01311567ffb13180e6b4eb111824628e4885" integrity sha512-2Ma9h81EJ0PRb9n4sW0i8KZlcnpTQfKxcj87zvi5DFe1fd8CTDEdseHDotK2beuA2l+LbgVPfd8EHaBJKm/Y8g== @@ -4355,6 +4377,21 @@ broccoli-debug@^0.6.5: symlink-or-copy "^1.1.8" tree-sync "^1.2.2" +broccoli-dependency-funnel@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/broccoli-dependency-funnel/-/broccoli-dependency-funnel-2.1.2.tgz#44126dd67ef2c68c4e78edeb0315e78fae9ab0ff" + integrity sha512-k6b0OnNuRcUnJ9TXA0o6RvqXOkTQ6APKoLsZeMJHAe/YjLjE1uTlfw4Z88GfGmi8gwtLHdnkrhBoJ7YdIkcVZA== + dependencies: + broccoli-plugin "^1.3.1" + fs-tree-diff "^0.5.9" + heimdalljs "^0.2.5" + heimdalljs-logger "^0.1.9" + mkdirp "^0.5.1" + mr-dep-walk "^1.4.0" + path-posix "^1.0.0" + rimraf "^2.6.2" + symlink-or-copy "^1.2.0" + broccoli-file-creator@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/broccoli-file-creator/-/broccoli-file-creator-2.1.1.tgz#7351dd2496c762cfce7736ce9b49e3fce0c7b7db" @@ -4686,6 +4723,18 @@ broccoli-templater@^2.0.1: rimraf "^2.6.2" walk-sync "^0.3.3" +broccoli-test-helper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/broccoli-test-helper/-/broccoli-test-helper-2.0.0.tgz#1cfbb76f7e856ad8df96d55ee2f5e0dddddf5d4f" + integrity sha512-TKwh8dBT+RcxKEG+vAoaRRhZsCMwZIHPZbCzBNCA0nUi1aoFB/LVosqwMC6H9Ipe06FxY5hpQxDLFbnBMdUPsA== + dependencies: + "@types/tmp" "^0.0.33" + broccoli "^2.0.0" + fixturify "^0.3.2" + fs-tree-diff "^0.5.9" + tmp "^0.0.33" + walk-sync "^0.3.3" + broccoli-uglify-sourcemap@^2.1.1: version "2.2.0" resolved "https://registry.yarnpkg.com/broccoli-uglify-sourcemap/-/broccoli-uglify-sourcemap-2.2.0.tgz#2ff49389bdf342a550c3596750ba2dde95a8f7d4" @@ -6816,6 +6865,19 @@ ember-api-actions@^0.1.8: "@mike-north/js-lib-semantic-release-config" "^0.0.0-development" semantic-release "^15.9.12" +ember-asset-loader@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/ember-asset-loader/-/ember-asset-loader-0.5.1.tgz#7a1a1b2a1c6a4185b222a2ead7214b0a6368d619" + integrity sha512-+suNUO9Ncxj6S3YSyZpatD46UYKhynVHOv0Y3VpKe2esB/HWDM5LZYHCQAHoM2ea8pIYvMCLqwmCZurYznbqmA== + dependencies: + broccoli-caching-writer "^3.0.3" + broccoli-funnel "^2.0.2" + broccoli-merge-trees "^3.0.2" + ember-cli-babel "^7.5.0" + fs-extra "^7.0.1" + object-assign "^4.1.0" + walk-sync "^1.1.3" + 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" @@ -7317,7 +7379,7 @@ ember-cli-version-checker@^2.0.0, ember-cli-version-checker@^2.1.0, ember-cli-ve resolve "^1.3.3" semver "^5.3.0" -ember-cli-version-checker@^3.1.2: +ember-cli-version-checker@^3.0.1, ember-cli-version-checker@^3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/ember-cli-version-checker/-/ember-cli-version-checker-3.1.3.tgz#7c9b4f5ff30fdebcd480b1c06c4de43bb51c522c" integrity sha512-PZNSvpzwWgv68hcXxyjREpj3WWb81A7rtYNQq1lLEgrWIchF8ApKJjWP3NBpHjaatwILkZAV8klair5WFlXAKg== @@ -7536,6 +7598,30 @@ ember-debug-handlers-polyfill@^1.1.1: resolved "https://registry.yarnpkg.com/ember-debug-handlers-polyfill/-/ember-debug-handlers-polyfill-1.1.1.tgz#e9ae0a720271a834221179202367421b580002ef" integrity sha512-lO7FBAqJjzbL+IjnWhVfQITypPOJmXdZngZR/Vdn513W4g/Q6Sjicao/mDzeDCb48Y70C4Facwk0LjdIpSZkRg== +ember-engines@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/ember-engines/-/ember-engines-0.7.0.tgz#77e2d9c6bcb3878e8e087ea354df4fc8cc187954" + integrity sha512-XuKg7J2yl+KJVnYDHxr9RYon5/Dcm6zb1YyWL9GZvSWm+SPwoIPa/5awSOOAT2vH76t7JfYVP6Nz/6zaGgNqtw== + dependencies: + amd-name-resolver "1.3.1" + babel-plugin-compact-reexports "^1.1.0" + broccoli-babel-transpiler "^7.1.2" + broccoli-concat "^3.7.3" + broccoli-debug "^0.6.5" + broccoli-dependency-funnel "^2.1.2" + broccoli-file-creator "^2.1.1" + broccoli-funnel "^2.0.2" + broccoli-merge-trees "^3.0.2" + broccoli-test-helper "^2.0.0" + calculate-cache-key-for-tree "^1.1.0" + ember-asset-loader "^0.5.1" + ember-cli-babel "^7.4.3" + ember-cli-preprocess-registry "^3.1.2" + ember-cli-string-utils "^1.1.0" + ember-cli-version-checker "^3.0.1" + ember-maybe-import-regenerator "^0.1.6" + lodash "^4.17.11" + ember-export-application-global@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ember-export-application-global/-/ember-export-application-global-2.0.0.tgz#8d6d7619ac8a1a3f8c43003549eb21ebed685bd2" @@ -8861,7 +8947,7 @@ fixturify-project@^1.5.3: fixturify "^0.3.4" tmp "^0.0.33" -fixturify@^0.3.4: +fixturify@^0.3.2, fixturify@^0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/fixturify/-/fixturify-0.3.4.tgz#c676de404a7f8ee8e64d0b76118e62ec95ab7b25" integrity sha512-Gx+KSB25b6gMc4bf7UFRTA85uE0iZR+RYur0JHh6dg4AGBh0EksOv4FCHyM7XpGmiJO7Bc7oV7vxENQBT+2WEQ== @@ -9012,6 +9098,15 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" +fs-extra@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" + integrity sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + fs-extra@^4.0.2, fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -11073,6 +11168,13 @@ jsonfile@^2.1.0: optionalDependencies: graceful-fs "^4.1.6" +jsonfile@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" + integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY= + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -12691,6 +12793,15 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mr-dep-walk@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/mr-dep-walk/-/mr-dep-walk-1.4.0.tgz#c8cd4223ceb10544ac7a4dd405c08451a328e054" + integrity sha512-UaDUqkLsd0ep3jAx2+A7BIpfw8wKxhthDj3yPNLBnevipK1CUFJJiz24jRVLw18q7R2aEiRq13WwUBlnwfbQqQ== + dependencies: + acorn "^5.1.1" + amd-name-resolver "^0.0.6" + fs-extra "^3.0.1" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -17907,7 +18018,7 @@ walk-sync@^0.3.0, walk-sync@^0.3.1, walk-sync@^0.3.2, walk-sync@^0.3.3: ensure-posix-path "^1.0.0" matcher-collection "^1.0.0" -walk-sync@^1.0.0: +walk-sync@^1.0.0, walk-sync@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-1.1.3.tgz#3b7b6468f068b5eba2278c931c57db3d39092969" integrity sha512-23ivbET0Q/389y3EHpiIgxx881AS2mwdXA7iBqUDNSymoTPYb2jWlF3gkuuAP1iLgdNXmiHw/kZ/wZwrELU6Ag==