Update ui dependencies (#7244)
* be more specific about node version, and specify a yarn version * update ember, ember-cli, ember-data, ember-data-model-fragments * use router handlers to access transition information * fix shadowing of component helper * update ivy-codemirror, ember-cli-inject-live-reload * remove custom router service * don't use transition.queryParams * update ember-cli-deprecation-workflow * refactor kv v1 to use 'path' instead of 'id' on creation * fix auth-jwt-test and toolbar-link-test * update ember composable helpers * remove Ember.copy from test file * no more deprecations in the workflow * fix more secret tests * fix remaining failed tests * move select component to core because it's used by ttl-picker * generate new model class for each test instead of reusing an existing one * fix selectors on kmip tests * refactor how control groups construct urls from the new transition objects * add router service override back in, and have it be evented so that we can trigger router events on it * move stories and markdown files to core if the component lives in core * update ember-cli, ember-cli-babel, ember-auto-import * update base64js, date-fns, deepmerge, codemirror, broccoli-asset-rev * update linting rules * fix test selectors * update ember-api-actions, ember-concurrency, ember-load-initializers, escape-string-regexp, normalize.css, prettier-eslint-cli, jsdoc-to-markdown * remove test-results dir * update base64js, ember-cli-clipboard, ember-cli-sass, ember-cli-string-helpers, ember-cli-template-lint, ember-cli-uglify, ember-link-action * fix linting * run yarn install without restoring from cache * refactor how tests are run and handle the vault server subprocess * update makefile for new test task names * update circle config to use the new yarn task * fix writing the seal keys when starting the dev server * remove optional deps from the lockfile * don't ignore-optional on yarn install * remove errant console.log * update ember-basic-dropdown-hover, jsonlint, yargs-parser * update ember-cli-flash * add back optionalDeps * update @babel/core@7.5.5, ember-basic-dropdown@1.1.3, eslint-plugin-ember@6.8.2 * update storybook to the latest release * add a babel config with targets so that the ember babel plugin works properly * update ember-resolver, move ember-cli-storybook to devDependencies * revert normalize.css upgrade * silence fetchadapter warning for now * exclude 3rd party array helper now that ember includes one * fix switch and entity lookup styling * only add -root suffix if it's not in versions mode * make sure drop always has an array on the aws role form * fix labels like we did with the backport * update eslintignore * update the yarn version in the docker build file * update eslint ignore
This commit is contained in:
parent
e4be09ead5
commit
4a1013e915
|
@ -130,7 +130,7 @@ jobs:
|
|||
# Run Ember tests
|
||||
cd ui
|
||||
mkdir -p test-results/qunit
|
||||
yarn run test-oss
|
||||
yarn test:oss
|
||||
name: Test UI
|
||||
- store_artifacts:
|
||||
path: ui/test-results
|
||||
|
@ -561,7 +561,7 @@ workflows:
|
|||
# # Run Ember tests
|
||||
# cd ui
|
||||
# mkdir -p test-results/qunit
|
||||
# yarn run test-oss
|
||||
# yarn test:oss
|
||||
# name: Test UI
|
||||
# - store_artifacts:
|
||||
# path: ui/test-results
|
||||
|
|
|
@ -26,7 +26,7 @@ steps:
|
|||
# Run Ember tests
|
||||
cd ui
|
||||
mkdir -p test-results/qunit
|
||||
yarn run test-oss
|
||||
yarn test:oss
|
||||
- store_artifacts:
|
||||
path: ui/test-results
|
||||
- store_test_results:
|
||||
|
|
12
Makefile
12
Makefile
|
@ -142,9 +142,9 @@ static-assets:
|
|||
|
||||
test-ember:
|
||||
@echo "--> Installing JavaScript assets"
|
||||
@cd ui && yarn --ignore-optional
|
||||
@cd ui && yarn
|
||||
@echo "--> Running ember tests"
|
||||
@cd ui && yarn run test-oss
|
||||
@cd ui && yarn run test:oss
|
||||
|
||||
ember-ci-test: # Deprecated, to be removed soon.
|
||||
@echo "ember-ci-test is deprecated in favour of test-ui-browserstack"
|
||||
|
@ -161,13 +161,13 @@ check-browserstack-creds:
|
|||
|
||||
test-ui-browserstack: check-vault-in-path check-browserstack-creds
|
||||
@echo "--> Installing JavaScript assets"
|
||||
@cd ui && yarn --ignore-optional
|
||||
@cd ui && yarn
|
||||
@echo "--> Running ember tests in Browserstack"
|
||||
@cd ui && yarn run test:browserstack
|
||||
|
||||
ember-dist:
|
||||
@echo "--> Installing JavaScript assets"
|
||||
@cd ui && yarn --ignore-optional
|
||||
@cd ui && yarn
|
||||
@cd ui && npm rebuild node-sass
|
||||
@echo "--> Building Ember application"
|
||||
@cd ui && yarn run build
|
||||
|
@ -175,10 +175,10 @@ ember-dist:
|
|||
|
||||
ember-dist-dev:
|
||||
@echo "--> Installing JavaScript assets"
|
||||
@cd ui && yarn --ignore-optional
|
||||
@cd ui && yarn
|
||||
@cd ui && npm rebuild node-sass
|
||||
@echo "--> Building Ember application"
|
||||
@cd ui && yarn run build-dev
|
||||
@cd ui && yarn run build:dev
|
||||
|
||||
static-dist: ember-dist static-assets
|
||||
static-dist-dev: ember-dist-dev static-assets
|
||||
|
|
|
@ -16,7 +16,7 @@ RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
|
|||
RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
|
||||
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
|
||||
|
||||
RUN apt-get update -y && apt-get install -y -q nodejs yarn=1.12.1-1
|
||||
RUN apt-get update -y && apt-get install -y -q nodejs yarn=1.17.3
|
||||
|
||||
RUN rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
# dependencies
|
||||
/bower_components/
|
||||
/node_modules/
|
||||
/.storybook/
|
||||
/stories/
|
||||
|
||||
# misc
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// env: node
|
||||
module.exports = {
|
||||
parser: 'babel-eslint',
|
||||
root: true,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
shippedProposals: true,
|
||||
useBuiltIns: 'usage',
|
||||
corejs: '3',
|
||||
targets: ['last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions'],
|
||||
},
|
||||
],
|
||||
],
|
||||
plugins: [
|
||||
[
|
||||
'@babel/plugin-proposal-decorators',
|
||||
{
|
||||
legacy: true,
|
||||
},
|
||||
],
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
'@babel/plugin-syntax-dynamic-import',
|
||||
['@babel/plugin-proposal-object-rest-spread', { loose: true, useBuiltIns: true }],
|
||||
'babel-plugin-macros',
|
||||
['emotion', { sourceMap: true, autoLabel: true }],
|
||||
],
|
||||
};
|
|
@ -1,7 +1,6 @@
|
|||
import { configure, addParameters, addDecorator } from '@storybook/ember';
|
||||
import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport';
|
||||
import theme from './theme.js';
|
||||
import { assign } from '@ember/polyfills';
|
||||
|
||||
function loadStories() {
|
||||
// automatically import all files ending in *.stories.js
|
||||
|
@ -28,7 +27,7 @@ addDecorator(storyFn => {
|
|||
|
||||
// Create a div to wrap the Canvas tab with the applied styles.
|
||||
const element = document.createElement('div');
|
||||
assign(element.style, styles.style);
|
||||
Object.assign(element.style, styles.style);
|
||||
|
||||
const innerElement = document.createElement('div');
|
||||
const wormhole = document.createElement('div');
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<meta name="vault/config/environment" content="%7B%22modulePrefix%22%3A%22vault%22%2C%22environment%22%3A%22development%22%2C%22rootURL%22%3A%22/ui/%22%2C%22locationType%22%3A%22auto%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%7D%7D%2C%22APP%22%3A%7B%22POLLING_URLS%22%3A%5B%22sys/health%22%2C%22sys/replication/status%22%2C%22sys/seal-status%22%5D%2C%22NAMESPACE_ROOT_URLS%22%3A%5B%22sys/health%22%2C%22sys/seal-status%22%2C%22sys/license/features%22%5D%2C%22DEFAULT_PAGE_SIZE%22%3A15%2C%22LOG_TRANSITIONS%22%3Atrue%7D%2C%22flashMessageDefaults%22%3A%7B%22timeout%22%3A7000%2C%22sticky%22%3Afalse%7D%2C%22contentSecurityPolicyHeader%22%3A%22Content-Security-Policy%22%2C%22contentSecurityPolicyMeta%22%3Atrue%2C%22contentSecurityPolicy%22%3A%7B%22connect-src%22%3A%5B%22%27self%27%22%5D%2C%22img-src%22%3A%5B%22%27self%27%22%2C%22data%3A%22%5D%2C%22form-action%22%3A%5B%22%27none%27%22%5D%2C%22script-src%22%3A%5B%22%27self%27%22%5D%2C%22style-src%22%3A%5B%22%27unsafe-inline%27%22%2C%22%27self%27%22%5D%2C%22default-src%22%3A%5B%22%27none%27%22%5D%2C%22font-src%22%3A%5B%22%27self%27%22%5D%2C%22media-src%22%3A%5B%22%27self%27%22%5D%7D%2C%22emberData%22%3A%7B%22enableRecordDataRFCBuild%22%3Afalse%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
|
||||
<meta name="vault/config/environment" content="%7B%22modulePrefix%22%3A%22vault%22%2C%22environment%22%3A%22development%22%2C%22rootURL%22%3A%22%2Fui%2F%22%2C%22locationType%22%3A%22auto%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%7D%2C%22_JQUERY_INTEGRATION%22%3Afalse%7D%2C%22APP%22%3A%7B%22POLLING_URLS%22%3A%5B%22sys%2Fhealth%22%2C%22sys%2Freplication%2Fstatus%22%2C%22sys%2Fseal-status%22%5D%2C%22NAMESPACE_ROOT_URLS%22%3A%5B%22sys%2Fhealth%22%2C%22sys%2Fseal-status%22%2C%22sys%2Flicense%2Ffeatures%22%5D%2C%22DEFAULT_PAGE_SIZE%22%3A15%2C%22LOG_TRANSITIONS%22%3Atrue%7D%2C%22flashMessageDefaults%22%3A%7B%22timeout%22%3A7000%2C%22sticky%22%3Afalse%7D%2C%22contentSecurityPolicyHeader%22%3A%22Content-Security-Policy%22%2C%22contentSecurityPolicyMeta%22%3Atrue%2C%22contentSecurityPolicy%22%3A%7B%22connect-src%22%3A%5B%22'self'%22%5D%2C%22img-src%22%3A%5B%22'self'%22%2C%22data%3A%22%5D%2C%22form-action%22%3A%5B%22'none'%22%5D%2C%22script-src%22%3A%5B%22'self'%22%5D%2C%22style-src%22%3A%5B%22'unsafe-inline'%22%2C%22'self'%22%5D%2C%22default-src%22%3A%5B%22'none'%22%5D%2C%22font-src%22%3A%5B%22'self'%22%5D%2C%22media-src%22%3A%5B%22'self'%22%5D%7D%2C%22exportApplicationGlobal%22%3Atrue%7D" />
|
||||
<meta name="kmip/config/environment" content="%7B%22modulePrefix%22%3A%22kmip%22%2C%22environment%22%3A%22development%22%7D" />
|
||||
<meta name="open-api-explorer/config/environment" content="%7B%22modulePrefix%22%3A%22open-api-explorer%22%2C%22environment%22%3A%22development%22%2C%22APP%22%3A%7B%22NAMESPACE_ROOT_URLS%22%3A%5B%22sys/health%22%2C%22sys/seal-status%22%2C%22sys/license/features%22%5D%7D%7D" />
|
||||
<meta name="replication/config/environment" content="%7B%22modulePrefix%22%3A%22replication%22%2C%22environment%22%3A%22development%22%7D" />
|
||||
<meta name="vault/config/asset-manifest" content="%7B%22bundles%22%3A%7B%22replication%22%3A%7B%22assets%22%3A%5B%7B%22uri%22%3A%22/ui/engines-dist/replication/assets/engine-vendor.js%22%2C%22type%22%3A%22js%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/replication/assets/engine.js%22%2C%22type%22%3A%22js%22%7D%5D%7D%7D%7D" />
|
||||
<meta name="vault/config/asset-manifest" content="%7B%22bundles%22%3A%7B%22kmip%22%3A%7B%22assets%22%3A%5B%7B%22uri%22%3A%22/ui/engines-dist/kmip/assets/engine-vendor.js%22%2C%22type%22%3A%22js%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/kmip/assets/engine.js%22%2C%22type%22%3A%22js%22%7D%5D%7D%2C%22open-api-explorer%22%3A%7B%22assets%22%3A%5B%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine-vendor.css%22%2C%22type%22%3A%22css%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine-vendor.js%22%2C%22type%22%3A%22js%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine.css%22%2C%22type%22%3A%22css%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/open-api-explorer/assets/engine.js%22%2C%22type%22%3A%22js%22%7D%5D%7D%2C%22replication%22%3A%7B%22assets%22%3A%5B%7B%22uri%22%3A%22/ui/engines-dist/replication/assets/engine-vendor.js%22%2C%22type%22%3A%22js%22%7D%2C%7B%22uri%22%3A%22/ui/engines-dist/replication/assets/engine.js%22%2C%22type%22%3A%22js%22%7D%5D%7D%7D%7D" />
|
||||
<link rel="stylesheet" href="/assets/vendor.css" />
|
||||
<link rel="stylesheet" href="/assets/vault.css" />
|
||||
<link rel="icon" href="/favicon.png" />
|
||||
|
|
|
@ -9,8 +9,11 @@ export default ApplicationAdapter.extend({
|
|||
const serializer = store.serializerFor(type.modelName);
|
||||
const data = serializer.serialize(snapshot);
|
||||
const { id } = snapshot;
|
||||
|
||||
return this.ajax(this.urlForSecret(snapshot.attr('backend'), id), 'POST', { data });
|
||||
const path = snapshot.record.path;
|
||||
return this.ajax(this.urlForSecret(snapshot.attr('backend'), path || id), 'POST', { data }).then(() => {
|
||||
data.id = path || id;
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
createRecord() {
|
||||
|
|
|
@ -158,22 +158,18 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
|
|||
return this.secretDataIsAdvanced || this.preferAdvancedEdit;
|
||||
}),
|
||||
|
||||
isWriteWithoutRead: computed(
|
||||
'model.{failedServerRead,selectedVersion.failedServerRead}',
|
||||
'isV2',
|
||||
function() {
|
||||
if (!this.model) return;
|
||||
// if the version couldn't be read from the server
|
||||
if (this.isV2 && this.model.selectedVersion.failedServerRead) {
|
||||
return true;
|
||||
}
|
||||
// if the model couldn't be read from the server
|
||||
if (!this.isV2 && this.model.failedServerRead) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
isWriteWithoutRead: computed('model.failedServerRead', 'modelForData.failedServerRead', 'isV2', function() {
|
||||
if (!this.model) return;
|
||||
// if the version couldn't be read from the server
|
||||
if (this.isV2 && this.modelForData.failedServerRead) {
|
||||
return true;
|
||||
}
|
||||
),
|
||||
// if the model couldn't be read from the server
|
||||
if (!this.isV2 && this.model.failedServerRead) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}),
|
||||
|
||||
transitionToRoute() {
|
||||
return this.router.transitionTo(...arguments);
|
||||
|
@ -307,12 +303,12 @@ export default Component.extend(FocusOnInsertMixin, WithNavToNearestAncestor, {
|
|||
let model = this.modelForData;
|
||||
// prevent from submitting if there's no key
|
||||
// maybe do something fancier later
|
||||
if (type === 'create' && isBlank(model.get('path') || model.id)) {
|
||||
if (type === 'create' && isBlank(model.path || model.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.persistKey(() => {
|
||||
this.transitionToRoute(SHOW_ROUTE, this.model.id);
|
||||
this.transitionToRoute(SHOW_ROUTE, this.model.path || this.model.id);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ export function linkParams({ mode, secret, queryParams }) {
|
|||
let params;
|
||||
const route = `vault.cluster.secrets.backend.${mode}`;
|
||||
|
||||
if (!secret || secret === ' ') {
|
||||
if ((mode !== 'versions' && !secret) || secret === ' ') {
|
||||
params = [route + '-root'];
|
||||
} else {
|
||||
params = [route, encodePath(secret)];
|
||||
|
|
|
@ -14,10 +14,10 @@ export default Helper.extend({
|
|||
|
||||
if (interval) {
|
||||
/*
|
||||
* NOTE: intentionally a setTimeout so tests do not block on it
|
||||
* as the run loop queue is never clear so tests will stay locked waiting
|
||||
* for queue to clear.
|
||||
*/
|
||||
* NOTE: intentionally a setTimeout so tests do not block on it
|
||||
* as the run loop queue is never clear so tests will stay locked waiting
|
||||
* for queue to clear.
|
||||
*/
|
||||
this.intervalTimer = setTimeout(() => {
|
||||
run(() => this.recompute());
|
||||
}, parseInt(interval, 10));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!DOCTYPE html lang="en">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
|
|
@ -5,17 +5,17 @@ import utils from 'vault/lib/key-utils';
|
|||
export default Mixin.create({
|
||||
// what attribute has the path for the key
|
||||
// will.be 'path' for v2 or 'id' v1
|
||||
pathAttr: 'id',
|
||||
pathAttr: 'path',
|
||||
flags: null,
|
||||
|
||||
initialParentKey: null,
|
||||
|
||||
isCreating: computed('initialParentKey', function() {
|
||||
return this.get('initialParentKey') != null;
|
||||
return this.initialParentKey != null;
|
||||
}),
|
||||
|
||||
pathVal() {
|
||||
return this.get(this.pathAttr);
|
||||
return this[this.pathAttr] || this.id;
|
||||
},
|
||||
|
||||
// rather than using defineProperty for all of these,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Mixin from '@ember/object/mixin';
|
||||
import removeRecord from 'vault/utils/remove-record';
|
||||
|
||||
// removes Ember Data records from the cache when the model
|
||||
// changes or you move away from the current route
|
||||
|
@ -10,7 +11,7 @@ export default Mixin.create({
|
|||
if (!model || !model.unloadRecord) {
|
||||
return;
|
||||
}
|
||||
this.store.unloadRecord(model);
|
||||
removeRecord(this.store, model);
|
||||
model.destroy();
|
||||
// it's important to unset the model on the controller since controllers are singletons
|
||||
this.controller.set(modelPath, null);
|
||||
|
|
|
@ -5,6 +5,7 @@ import { bool } from '@ember/object/computed';
|
|||
const { attr, belongsTo } = DS;
|
||||
|
||||
export default Secret.extend({
|
||||
failedServerRead: attr('boolean'),
|
||||
pathAttr: 'path',
|
||||
version: attr('number'),
|
||||
secret: belongsTo('secret-v2'),
|
||||
|
|
|
@ -8,6 +8,7 @@ import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
|||
const { attr, hasMany, belongsTo, Model } = DS;
|
||||
|
||||
export default Model.extend(KeyMixin, {
|
||||
failedServerRead: attr('boolean'),
|
||||
engine: belongsTo('secret-engine', { async: false }),
|
||||
engineId: attr('string'),
|
||||
versions: hasMany('secret-v2-version', { async: false, inverse: null }),
|
||||
|
|
|
@ -6,6 +6,7 @@ const { attr } = DS;
|
|||
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
||||
|
||||
export default DS.Model.extend(KeyMixin, {
|
||||
failedServerRead: attr('boolean'),
|
||||
auth: attr('string'),
|
||||
lease_duration: attr('number'),
|
||||
lease_id: attr('string'),
|
||||
|
|
|
@ -23,6 +23,7 @@ export default Route.extend({
|
|||
}
|
||||
|
||||
let router = this.get('routing');
|
||||
//FIXME transition.intent likely needs to be replaced
|
||||
let errorURL = transition.intent.url;
|
||||
let { name, contexts, queryParams } = transition.intent;
|
||||
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default Route.extend({
|
||||
router: service(),
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.router.on('routeWillChange', transition => {
|
||||
this.set('myTargetRouteName', transition.to.name);
|
||||
});
|
||||
},
|
||||
renderTemplate() {
|
||||
let { targetName } = this._router.currentState.routerJs.activeTransition;
|
||||
let targetName = this.myTargetRouteName;
|
||||
let isCallback =
|
||||
targetName === 'vault.cluster.oidc-callback' || targetName === 'vault.cluster.oidc-callback-namespace';
|
||||
if (isCallback) {
|
||||
|
|
|
@ -6,8 +6,9 @@ let secretModel = (store, backend, key) => {
|
|||
let backendModel = store.peekRecord('secret-engine', backend);
|
||||
let modelType = backendModel.get('modelTypeForKV');
|
||||
if (modelType !== 'secret-v2') {
|
||||
let model = store.createRecord(modelType);
|
||||
model.set('id', key);
|
||||
let model = store.createRecord(modelType, {
|
||||
path: key,
|
||||
});
|
||||
return model;
|
||||
}
|
||||
let secret = store.createRecord(modelType);
|
||||
|
@ -33,7 +34,8 @@ export default EditBase.extend({
|
|||
}
|
||||
return this.store.createRecord(modelType);
|
||||
}
|
||||
return secretModel(this.store, backend, transition.queryParams.initialKey);
|
||||
|
||||
return secretModel(this.store, backend, transition.to.queryParams.initialKey);
|
||||
},
|
||||
|
||||
model(params, transition) {
|
||||
|
|
|
@ -127,9 +127,12 @@ export default Route.extend(UnloadModelRoute, {
|
|||
try {
|
||||
if (secretModel.failedServerRead) {
|
||||
// we couldn't read metadata, so we want to directly fetch the version
|
||||
versionModel = await this.store.findRecord('secret-v2-version', JSON.stringify(versionId), {
|
||||
reload: true,
|
||||
});
|
||||
|
||||
versionModel =
|
||||
this.store.peekRecord('secret-v2-version', JSON.stringify(versionId)) ||
|
||||
(await this.store.findRecord('secret-v2-version', JSON.stringify(versionId), {
|
||||
reload: true,
|
||||
}));
|
||||
} else {
|
||||
// we may have previously errored, so roll it back here
|
||||
version.rollbackAttributes();
|
||||
|
@ -142,18 +145,20 @@ export default Route.extend(UnloadModelRoute, {
|
|||
if (error.httpStatus === 403 && capabilities.get('canUpdate')) {
|
||||
// versionModel is then a partial model from the metadata (if we have read there), or
|
||||
// we need to create one on the client
|
||||
versionModel = version || this.store.createRecord('secret-v2-version');
|
||||
versionModel.setProperties({
|
||||
failedServerRead: true,
|
||||
});
|
||||
// if it was created on the client we need to trigger an event via ember-data
|
||||
// so that it won't try to create the record on save
|
||||
if (versionModel.isNew) {
|
||||
versionModel.set('id', JSON.stringify(versionId));
|
||||
//TODO make this a util to better show what's happening
|
||||
// this is because we want the ember-data model save to call update instead of create
|
||||
// in the adapter so we have to force the frontend model to a "saved" state
|
||||
versionModel.send('pushedData');
|
||||
if (version) {
|
||||
version.set('failedServerRead', true);
|
||||
versionModel = version;
|
||||
} else {
|
||||
this.store.push({
|
||||
data: {
|
||||
type: 'secret-v2-version',
|
||||
id: JSON.stringify(versionId),
|
||||
attributes: {
|
||||
failedServerRead: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
versionModel = this.store.peekRecord('secret-v2-version', JSON.stringify(versionId));
|
||||
}
|
||||
} else {
|
||||
throw error;
|
||||
|
@ -162,18 +167,23 @@ export default Route.extend(UnloadModelRoute, {
|
|||
return versionModel;
|
||||
},
|
||||
|
||||
handleSecretModelError(capabilities, secret, modelType, error) {
|
||||
handleSecretModelError(capabilities, secretId, modelType, error) {
|
||||
// can't read the path and don't have update capability, so re-throw
|
||||
if (!capabilities.get('canUpdate') && modelType === 'secret') {
|
||||
throw error;
|
||||
}
|
||||
// don't have access to the metadata for v2 or the secret for v1,
|
||||
// so we make a stub model and mark it as `failedServerRead`
|
||||
let secretModel = this.store.createRecord(modelType);
|
||||
secretModel.setProperties({
|
||||
id: secret,
|
||||
failedServerRead: true,
|
||||
this.store.push({
|
||||
data: {
|
||||
id: secretId,
|
||||
type: modelType,
|
||||
attributes: {
|
||||
failedServerRead: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
let secretModel = this.store.peekRecord(modelType, secretId);
|
||||
return secretModel;
|
||||
},
|
||||
|
||||
|
|
|
@ -4,7 +4,12 @@ import ApplicationSerializer from './application';
|
|||
export default ApplicationSerializer.extend({
|
||||
secretDataPath: 'data',
|
||||
normalizeItems(payload, requestType) {
|
||||
if (requestType !== 'queryRecord' && payload.data.keys && Array.isArray(payload.data.keys)) {
|
||||
if (
|
||||
requestType !== 'queryRecord' &&
|
||||
payload.data &&
|
||||
payload.data.keys &&
|
||||
Array.isArray(payload.data.keys)
|
||||
) {
|
||||
// if we have data.keys, it's a list of ids, so we map over that
|
||||
// and create objects with id's
|
||||
return payload.data.keys.map(secret => {
|
||||
|
|
|
@ -95,17 +95,29 @@ export default Service.extend({
|
|||
return RSVP.reject(error);
|
||||
},
|
||||
|
||||
urlFromTransition(transition) {
|
||||
let routes = Object.keys(transition.params);
|
||||
let params = [];
|
||||
for (let route of routes) {
|
||||
let param = transition.params[route];
|
||||
if (Object.keys(param).length) {
|
||||
params.push(param);
|
||||
paramsFromTransition(transitionTo, params, queryParams) {
|
||||
let returnedParams = params.slice();
|
||||
let qps = queryParams;
|
||||
transitionTo.paramNames.map(name => {
|
||||
let param = transitionTo.params[name];
|
||||
if (param.length) {
|
||||
// push on to the front of the array since were're started at the end
|
||||
returnedParams.unshift(param);
|
||||
}
|
||||
});
|
||||
qps = { ...queryParams, ...transitionTo.queryParams };
|
||||
// if there's a parent transition, recurse to get its route params
|
||||
if (transitionTo.parent) {
|
||||
[returnedParams, qps] = this.paramsFromTransition(transitionTo.parent, returnedParams, qps);
|
||||
}
|
||||
let url = this.get('router').urlFor(transition.targetName, ...params, {
|
||||
queryParams: transition.queryParams,
|
||||
return [returnedParams, qps];
|
||||
},
|
||||
|
||||
urlFromTransition(transitionObj) {
|
||||
let transition = transitionObj.to;
|
||||
let [params, queryParams] = this.paramsFromTransition(transition, [], {});
|
||||
let url = this.get('router').urlFor(transition.name, ...params, {
|
||||
queryParams,
|
||||
});
|
||||
return url.replace('/ui', '');
|
||||
},
|
||||
|
|
|
@ -144,7 +144,8 @@ export default Service.extend({
|
|||
return pathName.includes(k) || pathName.includes(k.replace(/\/$/, ''));
|
||||
});
|
||||
const hasMatchingPath =
|
||||
(matchingPath && !this.isDenied(globPaths[matchingPath])) || globPaths.hasOwnProperty('');
|
||||
(matchingPath && !this.isDenied(globPaths[matchingPath])) ||
|
||||
Object.prototype.hasOwnProperty.call(globPaths, '');
|
||||
|
||||
if (matchingPath && capability) {
|
||||
return this.hasCapability(globPaths[matchingPath], capability) && hasMatchingPath;
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
import Evented from '@ember/object/evented';
|
||||
import Service from '@ember/service';
|
||||
|
||||
import { inject as service } from '@ember/service';
|
||||
import { alias } from '@ember/object/computed';
|
||||
|
||||
let hasOwn = (obj, prop) => {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
};
|
||||
|
||||
export function extractRouteArgs(args) {
|
||||
args = args.slice();
|
||||
let possibleQueryParams = args[args.length - 1];
|
||||
|
||||
let queryParams;
|
||||
if (possibleQueryParams && possibleQueryParams.hasOwnProperty('queryParams')) {
|
||||
if (possibleQueryParams && hasOwn(possibleQueryParams, 'queryParams')) {
|
||||
queryParams = args.pop().queryParams;
|
||||
} else {
|
||||
queryParams = {};
|
||||
|
@ -22,7 +29,7 @@ export function shallowEqual(a, b) {
|
|||
let aCount = 0;
|
||||
let bCount = 0;
|
||||
for (k in a) {
|
||||
if (a.hasOwnProperty(k)) {
|
||||
if (hasOwn(a, k)) {
|
||||
if (a[k] !== b[k]) {
|
||||
return false;
|
||||
}
|
||||
|
@ -31,7 +38,7 @@ export function shallowEqual(a, b) {
|
|||
}
|
||||
|
||||
for (k in b) {
|
||||
if (b.hasOwnProperty(k)) {
|
||||
if (hasOwn(b, k)) {
|
||||
bCount++;
|
||||
}
|
||||
}
|
||||
|
@ -39,31 +46,43 @@ export function shallowEqual(a, b) {
|
|||
return aCount === bCount;
|
||||
}
|
||||
|
||||
export default Service.extend({
|
||||
export default Service.extend(Evented, {
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
this._router.on('routeWillChange', transition => {
|
||||
this.trigger('routeWillChange', transition);
|
||||
});
|
||||
|
||||
this._router.on('routeDidChange', transition => {
|
||||
this.trigger('routeDidChange', transition);
|
||||
});
|
||||
},
|
||||
|
||||
routing: service('-routing'),
|
||||
router: alias('routing.router'),
|
||||
_router: alias('routing.router'),
|
||||
transitionTo() {
|
||||
let r = this.router;
|
||||
let r = this._router;
|
||||
return r.transitionTo.call(r, ...arguments);
|
||||
},
|
||||
replaceWith() {
|
||||
let r = this.router;
|
||||
let r = this._router;
|
||||
return r.replaceWith.call(r, ...arguments);
|
||||
},
|
||||
urlFor() {
|
||||
let r = this.router;
|
||||
let r = this._router;
|
||||
return r.generate.call(r, ...arguments);
|
||||
},
|
||||
currentURL: alias('router.currentURL'),
|
||||
currentRouteName: alias('router.currentRouteName'),
|
||||
rootURL: alias('router.rootURL'),
|
||||
location: alias('router.location'),
|
||||
currentURL: alias('_router.currentURL'),
|
||||
currentRouteName: alias('_router.currentRouteName'),
|
||||
rootURL: alias('_router.rootURL'),
|
||||
location: alias('_router.location'),
|
||||
|
||||
//adapted from:
|
||||
// https://github.com/emberjs/ember.js/blob/abf753a3d494830dc9e95b1337b3654b671b11be/packages/ember-routing/lib/services/router.js#L220
|
||||
isActive(...args) {
|
||||
let { routeName, models, queryParams } = extractRouteArgs(args);
|
||||
let routerMicrolib = this.router._routerMicrolib;
|
||||
let routerMicrolib = this._router._routerMicrolib;
|
||||
|
||||
if (!routerMicrolib.isActiveIntent(routeName, models, null)) {
|
||||
return false;
|
||||
|
@ -71,7 +90,7 @@ export default Service.extend({
|
|||
let hasQueryParams = Object.keys(queryParams).length > 0;
|
||||
|
||||
if (hasQueryParams) {
|
||||
this.router._prepareQueryParams(routeName, models, queryParams, true /* fromRouterService */);
|
||||
this._router._prepareQueryParams(routeName, models, queryParams, true /* fromRouterService */);
|
||||
return shallowEqual(queryParams, routerMicrolib.state.queryParams);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,11 @@
|
|||
.select {
|
||||
min-width: 190px;
|
||||
}
|
||||
}
|
||||
|
||||
label[for='namespace'] {
|
||||
padding: $spacing-xs;
|
||||
color: $grey;
|
||||
}
|
||||
.toolbar-label {
|
||||
padding: $spacing-xs;
|
||||
color: $grey;
|
||||
}
|
||||
|
||||
.toolbar-scroller {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
form {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
cursor: pointer;
|
||||
&.is-select-list {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
Multiple credential types is deprecated and you must choose one in order to save this role."
|
||||
/>
|
||||
{{/if}}
|
||||
{{#each (if (eq mode 'edit') (drop 1 model.fields) model.fields) as |attr|}}
|
||||
{{#each (if (eq mode 'edit') (drop 1 (or model.fields (array))) model.fields) as |attr|}}
|
||||
{{form-field data-test-field attr=attr model=model}}
|
||||
{{/each}}
|
||||
</div>
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
{{/if}}
|
||||
<div class="global-flash">
|
||||
{{#each flashMessages.queue as |flash|}}
|
||||
{{#flash-message data-test-flash-message=true flash=flash as |component flash close|}}
|
||||
{{#flash-message data-test-flash-message=true flash=flash as |customComponent flash close|}}
|
||||
{{#if flash.componentName}}
|
||||
{{component flash.componentName content=flash.content}}
|
||||
{{else}}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Unlinks a record from all its relationships and unloads it from
|
||||
// the store.
|
||||
export default function removeRecord(store, record) {
|
||||
let id = record.path || record.id;
|
||||
if (id) {
|
||||
// Collect relationship property names and types
|
||||
const relationshipMeta = [];
|
||||
record.eachRelationship((key, { kind }) => {
|
||||
relationshipMeta.push({ key, kind });
|
||||
});
|
||||
|
||||
// Push an update to this record with the relationships nulled out.
|
||||
// This unlinks the relationship from the models that aren't about to
|
||||
// be unloaded.
|
||||
store.push({
|
||||
data: {
|
||||
id,
|
||||
type: record.constructor.modelName,
|
||||
relationships: relationshipMeta.reduce((hash, rel) => {
|
||||
hash[rel.key] = { data: rel.kind === 'hasMany' ? [] : null };
|
||||
return hash;
|
||||
}, {}),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Now that the record has no attachments, it can be safely unloaded
|
||||
// from the store.
|
||||
store.unloadRecord(record);
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
/* global self */
|
||||
self.deprecationWorkflow = self.deprecationWorkflow || {};
|
||||
//self.deprecationWorkflow.config = {
|
||||
//throwOnUnhandled: true
|
||||
//}
|
||||
self.deprecationWorkflow.config = {
|
||||
workflow: [
|
||||
// ivy-codemirror and ember-radio-button still use send-action
|
||||
{ handler: 'silence', matchId: 'ember-component.send-action' },
|
||||
{ handler: 'silence', matchId: 'ember-runtime.deprecate-copy-copyable' },
|
||||
// ember-cli-page-object uses jquery's this.$() by default - this will change when we remove jquery
|
||||
{ handler: 'silence', matchId: 'ember-test-helpers.rendering-context.jquery-element' },
|
||||
// after ED 3.9 this shouldn't be necessary
|
||||
{ handler: 'silence', matchId: 'deprecate-fetch-ember-data-support' },
|
||||
],
|
||||
};
|
||||
|
|
|
@ -23,13 +23,12 @@ module.exports = function(defaults) {
|
|||
return `${config.rootURL.replace(/\/$/, '')}${filePath}`;
|
||||
},
|
||||
},
|
||||
|
||||
codemirror: {
|
||||
modes: ['javascript', 'ruby'],
|
||||
keyMaps: ['sublime'],
|
||||
},
|
||||
babel: {
|
||||
plugins: ['transform-object-rest-spread'],
|
||||
plugins: ['@babel/plugin-proposal-object-rest-spread'],
|
||||
},
|
||||
'ember-cli-babel': {
|
||||
includePolyfill: isTest || isProd || isCI,
|
||||
|
@ -50,12 +49,7 @@ module.exports = function(defaults) {
|
|||
browsers: ['defaults', 'ie 11'],
|
||||
},
|
||||
autoImport: {
|
||||
webpack: {
|
||||
// this makes `unsafe-eval` CSP unnecessary
|
||||
// see https://github.com/ef4/ember-auto-import/issues/50
|
||||
// and https://github.com/webpack/webpack/issues/5627
|
||||
devtool: 'inline-source-map',
|
||||
},
|
||||
forbidEval: true,
|
||||
},
|
||||
'ember-test-selectors': {
|
||||
strip: isProd,
|
||||
|
@ -64,6 +58,9 @@ module.exports = function(defaults) {
|
|||
'ember-fetch': {
|
||||
preferNative: true,
|
||||
},
|
||||
'ember-composable-helpers': {
|
||||
except: ['array'],
|
||||
},
|
||||
});
|
||||
|
||||
app.import('vendor/string-includes.js');
|
||||
|
@ -74,7 +71,7 @@ module.exports = function(defaults) {
|
|||
app.import('node_modules/codemirror/addon/lint/lint.css');
|
||||
app.import('node_modules/codemirror/addon/lint/lint.js');
|
||||
app.import('node_modules/codemirror/addon/lint/json-lint.js');
|
||||
app.import('node_modules/text-encoder-lite/index.js');
|
||||
app.import('node_modules/text-encoder-lite/text-encoder-lite.js');
|
||||
|
||||
app.import('app/styles/bulma/bulma-radio-checkbox.css');
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
import layout from '../templates/components/select';
|
||||
|
||||
/**
|
||||
* @module Select
|
||||
|
@ -21,6 +22,7 @@ import Component from '@ember/component';
|
|||
*/
|
||||
|
||||
export default Component.extend({
|
||||
layout,
|
||||
classNames: ['field'],
|
||||
label: null,
|
||||
selectedValue: null,
|
|
@ -41,29 +41,29 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
/*
|
||||
*
|
||||
* @public
|
||||
* @param String - ['array'|'string]
|
||||
*
|
||||
* Optional type for `inputValue` - defaults to `'array'`
|
||||
* Needs to match type of `inputValue` because it is set by the component on init.
|
||||
*
|
||||
*/
|
||||
*
|
||||
* @public
|
||||
* @param String - ['array'|'string]
|
||||
*
|
||||
* Optional type for `inputValue` - defaults to `'array'`
|
||||
* Needs to match type of `inputValue` because it is set by the component on init.
|
||||
*
|
||||
*/
|
||||
type: 'array',
|
||||
|
||||
/*
|
||||
*
|
||||
* @private
|
||||
* @param Ember.ArrayProxy
|
||||
*
|
||||
* mutable array that contains objects in the form of
|
||||
* {
|
||||
* value: 'somestring',
|
||||
* }
|
||||
*
|
||||
* used to track the state of values bound to the various inputs
|
||||
*
|
||||
*/
|
||||
*
|
||||
* @private
|
||||
* @param Ember.ArrayProxy
|
||||
*
|
||||
* mutable array that contains objects in the form of
|
||||
* {
|
||||
* value: 'somestring',
|
||||
* }
|
||||
*
|
||||
* used to track the state of values bound to the various inputs
|
||||
*
|
||||
*/
|
||||
/* eslint-disable ember/no-side-effects */
|
||||
inputList: computed(function() {
|
||||
return ArrayProxy.create({
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export { default } from 'core/components/select';
|
|
@ -1,9 +1,7 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './alert-banner.md';
|
||||
import { MESSAGE_TYPES } from '../lib/core/addon/helpers/message-types.js';
|
||||
|
||||
import { MESSAGE_TYPES } from '../addon/helpers/message-types.js';
|
||||
|
||||
storiesOf('Alerts/AlertBanner/', module)
|
||||
.addParameters({ options: { showPanel: false } })
|
|
@ -1,8 +1,7 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './alert-inline.md';
|
||||
import { MESSAGE_TYPES } from '../lib/core/addon/helpers/message-types.js';
|
||||
import { MESSAGE_TYPES } from '../addon/helpers/message-types.js';
|
||||
|
||||
storiesOf('Alerts/AlertInline/', module)
|
||||
.addParameters({ options: { showPanel: false } })
|
|
@ -1,21 +1,21 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
import notes from './chevron.md';
|
||||
|
||||
|
||||
storiesOf('Chevron/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(`Chevron`, () => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`Chevron`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Chevron</h5>
|
||||
<Chevron @direction={{direction}} />
|
||||
`,
|
||||
context: {
|
||||
direction: select('Direction', ['right', 'down', 'left', 'up'], 'right'),
|
||||
},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {
|
||||
direction: select('Direction', ['right', 'down', 'left', 'up'], 'right'),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
|
||||
|
@ -12,7 +11,8 @@ storiesOf('ConfirmAction/', module)
|
|||
})
|
||||
)
|
||||
.add(
|
||||
`ConfirmAction`, () => ({
|
||||
`ConfirmAction`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Confirm Action</h5>
|
||||
<ConfirmAction
|
|
@ -1,16 +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`
|
||||
.add(
|
||||
`DocLink`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Doc Link</h5>
|
||||
<DocLink @path="/docs/secrets/kv/kv-v2.html">Learn about KV v2</DocLink>
|
||||
`
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
`,
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -0,0 +1,44 @@
|
|||
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`
|
||||
<h5 class="title is-5">Empty State</h5>
|
||||
<EmptyState @title={{title}} @message={{message}} />
|
||||
`,
|
||||
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`
|
||||
<h5 class="title is-5">Empty State</h5>
|
||||
<EmptyState @title={{title}} @message={{message}}>
|
||||
<DocLink @path="/docs/secrets/kv/kv-v2.html">Learn about KV v2</DocLink>
|
||||
</EmptyState>
|
||||
`,
|
||||
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 }
|
||||
);
|
|
@ -1,8 +1,8 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
import notes from './form-field-groups.md';
|
||||
import { getOwner } from '@ember/application';
|
||||
|
||||
// This will need to be replaced with a fake model, since the form fields associated with
|
||||
// each model come from OpenApi and Storybook doesn't have a Vault server to call OpenApi from.
|
||||
|
@ -37,7 +37,7 @@ storiesOf('Form/FormFieldGroups/', module)
|
|||
context: {
|
||||
actions: {
|
||||
getModel(modelType) {
|
||||
return Ember.getOwner(this)
|
||||
return getOwner(this)
|
||||
.lookup('service:store')
|
||||
.createRecord(`auth-config/${modelType}`);
|
||||
},
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './form-field.md';
|
|
@ -1,12 +1,11 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './icon.md';
|
||||
import icons from '../node_modules/@hashicorp/structure-icons/dist/index.js';
|
||||
import icons from '../../../node_modules/@hashicorp/structure-icons/dist/index.js';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
|
||||
storiesOf('Icon/', module)
|
||||
.addParameters({ options: { showPanel: true} })
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(
|
||||
'Icon',
|
|
@ -1,36 +1,38 @@
|
|||
/* 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`
|
||||
.addDecorator(withKnobs({ escapeHTML: false }))
|
||||
.add(
|
||||
`InfoTableRow with text value`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Info Table Row</h5>
|
||||
<InfoTableRow @value={{value}} @label={{label}} @alwaysRender={{alwaysRender}} />
|
||||
`,
|
||||
context: {
|
||||
label: text('Label', 'TTL'),
|
||||
value: text('Value', '30m'),
|
||||
alwaysRender: boolean('Always render?', false),
|
||||
},
|
||||
}),
|
||||
{notes}
|
||||
context: {
|
||||
label: text('Label', 'TTL'),
|
||||
value: text('Value', '30m'),
|
||||
alwaysRender: boolean('Always render?', false),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
)
|
||||
.add(`InfoTableRow with boolean value`, () => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`InfoTableRow with boolean value`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Info Table Row</h5>
|
||||
<InfoTableRow @value={{value}} @label={{label}} @alwaysRender={{alwaysRender}} />
|
||||
`,
|
||||
context: {
|
||||
label: 'Local mount?',
|
||||
value: boolean('Value', true),
|
||||
alwaysRender: boolean('Always render?', true),
|
||||
},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {
|
||||
label: 'Local mount?',
|
||||
value: boolean('Value', true),
|
||||
alwaysRender: boolean('Always render?', true),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,16 +1,17 @@
|
|||
/* 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`
|
||||
.add(
|
||||
`LayoutLoading`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Layout Loading</h5>
|
||||
<LayoutLoading/>
|
||||
`,
|
||||
context: {},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, text, boolean } from '@storybook/addon-knobs';
|
|
@ -1,25 +1,27 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './message-error.md';
|
||||
import EmberObject from '@ember/object';
|
||||
|
||||
let model = Ember.Object.create({
|
||||
let model = EmberObject.create({
|
||||
adapterError: {
|
||||
message: 'This is an adapterError on the model'
|
||||
message: 'This is an adapterError on the model',
|
||||
},
|
||||
isError: true
|
||||
isError: true,
|
||||
});
|
||||
|
||||
storiesOf('MessageError/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.add(`MessageError`, () => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`MessageError`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Message Error</h5>
|
||||
<MessageError @model={{model}} />
|
||||
`,
|
||||
context: {
|
||||
model
|
||||
}
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {
|
||||
model,
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,13 +1,13 @@
|
|||
/* 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`
|
||||
.add(
|
||||
`PopupMenu`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Popup Menu</h5>
|
||||
<PopupMenu>
|
||||
<nav class="menu">
|
||||
|
@ -21,7 +21,7 @@ storiesOf('PopupMenu/', module)
|
|||
</nav>
|
||||
</PopupMenu>
|
||||
`,
|
||||
context: {},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, object, text, boolean, select } from '@storybook/addon-knobs';
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './toggle-button.md';
|
|
@ -1,14 +1,15 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
import { withKnobs } from '@storybook/addon-knobs';
|
||||
import notes from './toolbar-actions.md';
|
||||
|
||||
storiesOf('Toolbar/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(`ToolbarActions`, () => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`ToolbarActions`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">ToolbarActions</h5>
|
||||
<Toolbar>
|
||||
<ToolbarActions>
|
||||
|
@ -21,7 +22,7 @@ storiesOf('Toolbar/', module)
|
|||
</ToolbarActions>
|
||||
</Toolbar>
|
||||
`,
|
||||
context: {},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,15 +1,15 @@
|
|||
/* 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 './toolbar-download-button.md';
|
||||
|
||||
|
||||
storiesOf('Toolbar/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(`ToolbarDownloadButton`,() => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`ToolbarDownloadButton`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">ToolbarLink</h5>
|
||||
<div style="width: 400px;">
|
||||
<Toolbar>
|
||||
|
@ -21,9 +21,9 @@ storiesOf('Toolbar/', module)
|
|||
</Toolbar>
|
||||
</div>
|
||||
`,
|
||||
context: {
|
||||
label: text('Button text', 'Download policy'),
|
||||
},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {
|
||||
label: text('Button text', 'Download policy'),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,14 +1,15 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
import { withKnobs } from '@storybook/addon-knobs';
|
||||
import notes from './toolbar-filters.md';
|
||||
|
||||
storiesOf('Toolbar/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(`ToolbarFilters`, () => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`ToolbarFilters`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">ToolbarFilters</h5>
|
||||
<Toolbar>
|
||||
<ToolbarFilters>
|
||||
|
@ -29,7 +30,7 @@ storiesOf('Toolbar/', module)
|
|||
</ToolbarFilters>
|
||||
</Toolbar>
|
||||
`,
|
||||
context: {},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,15 +1,15 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select, text } from '@storybook/addon-knobs';
|
||||
import notes from './toolbar-link.md';
|
||||
|
||||
|
||||
storiesOf('Toolbar/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(`ToolbarLink`,() => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`ToolbarLink`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">ToolbarLink</h5>
|
||||
<div style="width: 400px;">
|
||||
<Toolbar>
|
||||
|
@ -24,10 +24,10 @@ storiesOf('Toolbar/', module)
|
|||
</Toolbar>
|
||||
</div>
|
||||
`,
|
||||
context: {
|
||||
type: select('Type', ['', 'add']),
|
||||
label: text('Button text', 'Edit secret'),
|
||||
},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {
|
||||
type: select('Type', ['', 'add']),
|
||||
label: text('Button text', 'Edit secret'),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,15 +1,15 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select, text } from '@storybook/addon-knobs';
|
||||
import notes from './toolbar-secret-link.md';
|
||||
|
||||
|
||||
storiesOf('Toolbar/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(`ToolbarSecretLink`,() => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`ToolbarSecretLink`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">ToolbarLink</h5>
|
||||
<div style="width: 400px;">
|
||||
<Toolbar>
|
||||
|
@ -27,10 +27,10 @@ storiesOf('Toolbar/', module)
|
|||
</Toolbar>
|
||||
</div>
|
||||
`,
|
||||
context: {
|
||||
type: select('Type', ['', 'add']),
|
||||
label: text('Button text', 'Edit role'),
|
||||
},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {
|
||||
type: select('Type', ['', 'add']),
|
||||
label: text('Button text', 'Edit role'),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import { withKnobs, select } from '@storybook/addon-knobs';
|
||||
|
@ -7,8 +6,10 @@ import notes from './toolbar.md';
|
|||
storiesOf('Toolbar/', module)
|
||||
.addParameters({ options: { showPanel: true } })
|
||||
.addDecorator(withKnobs())
|
||||
.add(`Toolbar`, () => ({
|
||||
template: hbs`
|
||||
.add(
|
||||
`Toolbar`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Toolbar</h5>
|
||||
<section class="box is-fullwidth is-shadowless">
|
||||
<h5 class="title is-6">Example for list views</h5>
|
||||
|
@ -72,9 +73,9 @@ storiesOf('Toolbar/', module)
|
|||
</Toolbar>
|
||||
</section>
|
||||
`,
|
||||
context: {
|
||||
example: select('Example', ['List', 'Show', 'Code editor'], 'List'),
|
||||
},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {
|
||||
example: select('Example', ['List', 'Show', 'Code editor'], 'List'),
|
||||
},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,16 +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`
|
||||
.add(
|
||||
`TtlPicker`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Ttl Picker</h5>
|
||||
<TtlPicker />
|
||||
`,
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
}),
|
||||
{ notes }
|
||||
);
|
|
@ -1,17 +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`
|
||||
.add(
|
||||
`VaultLogoSpinner`,
|
||||
() => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Vault Logo Spinner</h5>
|
||||
<VaultLogoSpinner/>
|
||||
`,
|
||||
context: {},
|
||||
}),
|
||||
{notes}
|
||||
);
|
||||
context: {},
|
||||
}),
|
||||
{ notes }
|
||||
);
|
146
ui/package.json
146
ui/package.json
|
@ -10,48 +10,47 @@
|
|||
},
|
||||
"scripts": {
|
||||
"build": "ember build -prod",
|
||||
"build-dev": "ember build",
|
||||
"lint:hbs": "ember-template-lint .",
|
||||
"build:dev": "ember build",
|
||||
"lint:hbs": "ember-template-lint app/**/* lib/**/*",
|
||||
"lint:js": "eslint .",
|
||||
"fmt": "yarn run fmt-js && yarn run fmt-styles",
|
||||
"fmt-js": "prettier-eslint --single-quote --no-use-tabs --trailing-comma es5 --print-width=110 --write '{app,tests,config,lib}/**/*.js'",
|
||||
"fmt-styles": "prettier --write app/styles/**/*.*",
|
||||
"fmt:js": "prettier-eslint --single-quote --no-use-tabs --trailing-comma es5 --print-width=110 --write '{app,tests,config,lib}/**/*.js'",
|
||||
"fmt:styles": "prettier --write app/styles/**/*.*",
|
||||
"start": "export VAULT_ADDR=http://localhost:8200; ember server --proxy=$VAULT_ADDR",
|
||||
"start2": "ember server --proxy=http://localhost:8202 --port=4202",
|
||||
"test": "node scripts/start-vault.js & yarn run lint:js & ember test",
|
||||
"test:browserstack": "export CI=true; node scripts/start-vault.js & node scripts/run-browserstack-tests.js",
|
||||
"test-oss": "yarn run test -f='!enterprise'",
|
||||
"test-quick": "node scripts/start-vault.js & ember test",
|
||||
"test-quick-oss": "yarn run test-quick -f='!enterprise'",
|
||||
"build-storybook": "build-storybook -s ../pkg/web_ui",
|
||||
"test": "yarn lint:js && node scripts/start-vault.js",
|
||||
"test:oss": "yarn run test -f='!enterprise'",
|
||||
"test:browserstack": "export CI=true; node scripts/start-vault.js --browserstack",
|
||||
"test:quick": "node scripts/start-vault.js",
|
||||
"test:quick-oss": "yarn test-quick -f='!enterprise'",
|
||||
"build:storybook": "build-storybook -s ../pkg/web_ui",
|
||||
"storybook": "start-storybook -p 6006 -s ../pkg/web_ui",
|
||||
"gen-story-md": "node scripts/gen-story-md.js"
|
||||
},
|
||||
"lint-staged": {
|
||||
"linters": {
|
||||
"*.js": [
|
||||
"prettier-eslint --single-quote --no-use-tabs --trailing-comma es5 --print-width 110 --write",
|
||||
"git add"
|
||||
],
|
||||
"*.scss": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
}
|
||||
"*.js": [
|
||||
"prettier-eslint --single-quote --no-use-tabs --trailing-comma es5 --print-width 110 --write",
|
||||
"git add"
|
||||
],
|
||||
"*.scss": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.5.5",
|
||||
"@ember/optional-features": "^0.7.0",
|
||||
"@hashicorp/structure-icons": "^1.3.0",
|
||||
"@storybook/ember-cli-storybook": "meirish/ember-cli-storybook#6bd58326d8c21e986d390b541ae5e49089d61b93",
|
||||
"Duration.js": "icholy/Duration.js#golang_compatible",
|
||||
"autosize": "^4.0.0",
|
||||
"babel-eslint": "^10.0.2",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.23.0",
|
||||
"base64-js": "1.2.1",
|
||||
"broccoli-asset-rev": "^2.7.0",
|
||||
"base64-js": "^1.3.1",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"broccoli-sri-hash": "meirish/broccoli-sri-hash#rooturl",
|
||||
"bulma": "^0.5.2",
|
||||
"bulma-switch": "^0.0.1",
|
||||
"codemirror": "5.15.2",
|
||||
"codemirror": "^5.48.2",
|
||||
"columnify": "^1.5.4",
|
||||
"cool-checkboxes-for-bulma.io": "^1.1.0",
|
||||
"d3-axis": "^1.0.8",
|
||||
|
@ -61,72 +60,71 @@
|
|||
"d3-time-format": "^2.1.1",
|
||||
"d3-tip": "^0.9.1",
|
||||
"d3-transition": "^1.2.0",
|
||||
"date-fns": "^1.29.0",
|
||||
"deepmerge": "^2.1.1",
|
||||
"date-fns": "^1.30.0",
|
||||
"deepmerge": "^4.0.0",
|
||||
"doctoc": "^1.4.0",
|
||||
"ember-api-actions": "^0.1.8",
|
||||
"ember-auto-import": "^1.2.3",
|
||||
"ember-api-actions": "^0.2.8",
|
||||
"ember-auto-import": "^1.5.2",
|
||||
"ember-basic-dropdown": "^1.0.0",
|
||||
"ember-basic-dropdown-hover": "^0.5.0",
|
||||
"ember-cli": "~3.5.1",
|
||||
"ember-basic-dropdown-hover": "^0.6.0",
|
||||
"ember-cli": "~3.11.0",
|
||||
"ember-cli-autoprefixer": "^0.8.1",
|
||||
"ember-cli-babel": "^6.16.0",
|
||||
"ember-cli-babel": "^7.8.0",
|
||||
"ember-cli-browserstack": "^0.0.7",
|
||||
"ember-cli-clipboard": "^0.8.0",
|
||||
"ember-cli-clipboard": "^0.13.0",
|
||||
"ember-cli-content-security-policy": "^1.0.0",
|
||||
"ember-cli-dependency-checker": "^3.0.0",
|
||||
"ember-cli-deprecation-workflow": "^1.0.1",
|
||||
"ember-cli-element-closest-polyfill": "^0.0.1",
|
||||
"ember-cli-flash": "1.7.1",
|
||||
"ember-cli-flash": "^1.7.2",
|
||||
"ember-cli-htmlbars": "^3.0.0",
|
||||
"ember-cli-htmlbars-inline-precompile": "^1.0.3",
|
||||
"ember-cli-inject-live-reload": "^1.8.2",
|
||||
"ember-cli-htmlbars-inline-precompile": "^2.1.0",
|
||||
"ember-cli-inject-live-reload": "^2.0.1",
|
||||
"ember-cli-page-object": "^1.15.3",
|
||||
"ember-cli-pretender": "^3.1.1",
|
||||
"ember-cli-sass": "^9.0.0",
|
||||
"ember-cli-sass": "^10.0.1",
|
||||
"ember-cli-sri": "meirish/ember-cli-sri#rooturl",
|
||||
"ember-cli-string-helpers": "^1.5.0",
|
||||
"ember-cli-template-lint": "^1.0.0-beta.1",
|
||||
"ember-cli-uglify": "^2.1.0",
|
||||
"ember-composable-helpers": "^2.0.3",
|
||||
"ember-computed-query": "^0.1.1",
|
||||
"ember-concurrency": "^0.10.0",
|
||||
"ember-cli-string-helpers": "^4.0.0",
|
||||
"ember-cli-template-lint": "^1.0.0-beta.3",
|
||||
"ember-cli-uglify": "^3.0.0",
|
||||
"ember-composable-helpers": "^2.3.1",
|
||||
"ember-concurrency": "^1.0.0",
|
||||
"ember-concurrency-test-waiter": "^0.3.1",
|
||||
"ember-copy": "^1.0.0",
|
||||
"ember-data": "~3.4.0",
|
||||
"ember-data-model-fragments": "^3.3.0",
|
||||
"ember-data": "~3.8.0",
|
||||
"ember-data-model-fragments": "^4.0.0",
|
||||
"ember-engines": "^0.8.0",
|
||||
"ember-export-application-global": "^2.0.0",
|
||||
"ember-fetch": "^6.5.1",
|
||||
"ember-inflector": "^3.0.0",
|
||||
"ember-link-action": "^0.1.2",
|
||||
"ember-load-initializers": "^1.1.0",
|
||||
"ember-link-action": "^1.0.0",
|
||||
"ember-load-initializers": "^2.0.0",
|
||||
"ember-maybe-import-regenerator": "^0.1.6",
|
||||
"ember-maybe-in-element": "^0.1.3",
|
||||
"ember-maybe-in-element": "^0.4.0",
|
||||
"ember-power-select-with-create": "cibernox/ember-power-select-with-create#6203918f247c1c5d692db4f9185ab8321d2125e1",
|
||||
"ember-qunit": "^4.4.1",
|
||||
"ember-radio-button": "^1.1.1",
|
||||
"ember-radio-button": "^2.0.1",
|
||||
"ember-resolver": "^5.0.1",
|
||||
"ember-responsive": "^3.0.0-beta.3",
|
||||
"ember-router-helpers": "^0.2.0",
|
||||
"ember-sinon": "^1.0.1",
|
||||
"ember-source": "~3.4.0",
|
||||
"ember-svg-jar": "^1.2.2",
|
||||
"ember-sinon": "^4.0.0",
|
||||
"ember-source": "~3.8.0",
|
||||
"ember-svg-jar": "^2.1.0",
|
||||
"ember-test-selectors": "^2.1.0",
|
||||
"ember-truth-helpers": "^2.1.0",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-config-prettier": "^3.1.0",
|
||||
"eslint-plugin-ember": "^6.3.0",
|
||||
"eslint-plugin-prettier": "^3.0.0",
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"eslint": "^6.1.0",
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"eslint-plugin-ember": "^6.7.0",
|
||||
"eslint-plugin-prettier": "^3.1.0",
|
||||
"flat": "^4.1.0",
|
||||
"ivy-codemirror": "2.1.0",
|
||||
"jsonlint": "1.6.0",
|
||||
"ivy-codemirror": "IvyApp/ivy-codemirror#fb09333c5144da47e14a9e6260f80577d5408374",
|
||||
"jsonlint": "^1.6.3",
|
||||
"loader.js": "^4.7.0",
|
||||
"node-sass": "^4.10.0",
|
||||
"normalize.css": "4.1.1",
|
||||
"prettier": "^1.14.3",
|
||||
"prettier-eslint-cli": "^4.7.1",
|
||||
"prettier-eslint-cli": "^5.0.0",
|
||||
"qunit-dom": "^0.7.1",
|
||||
"route-recognizer": "^0.3.4",
|
||||
"sass-svg-uri": "^1.0.0",
|
||||
|
@ -134,29 +132,29 @@
|
|||
"string.prototype.endswith": "^0.2.0",
|
||||
"string.prototype.startswith": "^0.2.0",
|
||||
"swagger-ui-dist": "^3.22.3",
|
||||
"text-encoder-lite": "1.0.0",
|
||||
"walk-sync": "^0.3.3",
|
||||
"text-encoder-lite": "2.0.0",
|
||||
"walk-sync": "^2.0.2",
|
||||
"xstate": "^3.3.3",
|
||||
"yargs-parser": "^13.0.0"
|
||||
"yargs-parser": "^13.1.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@babel/core": "^7.3.4",
|
||||
"@storybook/addon-knobs": "^5.0.5",
|
||||
"@storybook/addon-links": "^5.0.5",
|
||||
"@storybook/addon-notes": "^5.0.5",
|
||||
"@storybook/addon-viewport": "^5.0.5",
|
||||
"@storybook/addons": "^5.0.5",
|
||||
"@storybook/ember": "^5.0.5",
|
||||
"@storybook/ember-cli-storybook": "meirish/ember-cli-storybook#6bd58326d8c21e986d390b541ae5e49089d61b93",
|
||||
"babel-loader": "^8.0.5",
|
||||
"jsdoc-to-markdown": "^4.0.1",
|
||||
"lint-staged": "^8.0.4"
|
||||
"@babel/core": "^7.5.5",
|
||||
"@storybook/addon-knobs": "^5.1.10",
|
||||
"@storybook/addon-links": "^5.1.10",
|
||||
"@storybook/addon-notes": "^5.1.10",
|
||||
"@storybook/addon-viewport": "^5.1.10",
|
||||
"@storybook/addons": "^5.1.10",
|
||||
"@storybook/ember": "^5.1.10",
|
||||
"babel-loader": "^8.0.6",
|
||||
"jsdoc-to-markdown": "^5.0.0",
|
||||
"lint-staged": "^9.2.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"handlebars": "^4.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": " >= 10.*"
|
||||
"node": " >= 10.* <11",
|
||||
"yarn": "1.17.3"
|
||||
},
|
||||
"private": true,
|
||||
"ember-addon": {
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
/* eslint-env node */
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const execa = require('execa');
|
||||
const chalk = require('chalk');
|
||||
|
||||
function run(command, args = []) {
|
||||
console.log(chalk.dim('$ ' + command + ' ' + args.join(' ')));
|
||||
|
||||
let p = execa(command, args);
|
||||
p.stdout.pipe(process.stdout);
|
||||
p.stderr.pipe(process.stderr);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
(async function() {
|
||||
try {
|
||||
await run('ember', ['browserstack:connect']);
|
||||
try {
|
||||
await run('ember', ['test', '-f=secrets/secret/create', '-c', 'testem.browserstack.js']);
|
||||
|
||||
console.log('success');
|
||||
process.exit(0);
|
||||
} finally {
|
||||
if (process.env.CI === 'true') {
|
||||
await run('ember', ['browserstack:results']);
|
||||
}
|
||||
await run('ember', ['browserstack:disconnect']);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error');
|
||||
console.log(error);
|
||||
process.exit(1);
|
||||
}
|
||||
})();
|
|
@ -1,80 +1,104 @@
|
|||
#!/usr/bin/env node
|
||||
/* eslint-disable */
|
||||
/* eslint-env node */
|
||||
/* eslint-disable no-console */
|
||||
|
||||
if (process.argv[2]) {
|
||||
process.kill(process.argv[2], 'SIGINT');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.env.TERM = 'dumb';
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var readline = require('readline');
|
||||
var spawn = require('child_process').spawn;
|
||||
var vault = spawn('vault', [
|
||||
'server',
|
||||
'-dev',
|
||||
'-dev-ha',
|
||||
'-dev-transactional',
|
||||
'-dev-root-token-id=root',
|
||||
'-dev-listen-address=127.0.0.1:9200',
|
||||
]);
|
||||
var execa = require('execa');
|
||||
var chalk = require('chalk');
|
||||
|
||||
function run(command, args = [], shareStd = true) {
|
||||
console.log(chalk.dim('$ ' + command + ' ' + args.join(' ')));
|
||||
// cleanup means that execa will handle stopping the vault subprocess
|
||||
// inherit all of the stdin/out/err so that testem still works as if you were running it directly
|
||||
if (shareStd) {
|
||||
return execa(command, args, { cleanup: true, stdin: 'inherit', stdout: 'inherit', stderr: 'inherit' });
|
||||
}
|
||||
let p = execa(command, args, { cleanup: true });
|
||||
p.stdout.pipe(process.stdout);
|
||||
p.stderr.pipe(process.stderr);
|
||||
return p;
|
||||
}
|
||||
|
||||
var output = '';
|
||||
var unseal, root;
|
||||
var unseal, root, written;
|
||||
|
||||
readline
|
||||
.createInterface({
|
||||
input: vault.stdout,
|
||||
terminal: false,
|
||||
})
|
||||
.on('line', function(line) {
|
||||
output = output + line;
|
||||
console.log(line);
|
||||
var unsealMatch = output.match(/Unseal Key: (.+)$/m);
|
||||
if (unsealMatch && !unseal) {
|
||||
unseal = unsealMatch[1];
|
||||
}
|
||||
var rootMatch = output.match(/Root Token: (.+)$/m);
|
||||
if (rootMatch && !root) {
|
||||
root = rootMatch[1];
|
||||
}
|
||||
if (root && unseal) {
|
||||
fs.writeFile(
|
||||
path.join(process.cwd(), 'tests/helpers/vault-keys.js'),
|
||||
`export default ${JSON.stringify({ unseal, root }, null, 2)}`,
|
||||
err => {
|
||||
if (err) throw err;
|
||||
}
|
||||
);
|
||||
|
||||
console.log('VAULT SERVER READY');
|
||||
}
|
||||
async function processLines(input, eachLine = () => {}) {
|
||||
const rl = readline.createInterface({
|
||||
input,
|
||||
terminal: true,
|
||||
});
|
||||
for await (const line of rl) {
|
||||
eachLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
vault.stderr.on('data', function(data) {
|
||||
console.log(data.toString());
|
||||
});
|
||||
(async function() {
|
||||
try {
|
||||
let vault = run(
|
||||
'vault',
|
||||
[
|
||||
'server',
|
||||
'-dev',
|
||||
'-dev-ha',
|
||||
'-dev-transactional',
|
||||
'-dev-root-token-id=root',
|
||||
'-dev-listen-address=127.0.0.1:9200',
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
vault.on('close', function(code) {
|
||||
console.log(`child process exited with code ${code}`);
|
||||
process.exit();
|
||||
});
|
||||
vault.on('error', function(error) {
|
||||
console.log(`child process errored: ${error}`);
|
||||
process.exit();
|
||||
});
|
||||
processLines(vault.stdout, function(line) {
|
||||
if (written) {
|
||||
output = null;
|
||||
return;
|
||||
}
|
||||
output = output + line;
|
||||
var unsealMatch = output.match(/Unseal Key: (.+)$/m);
|
||||
if (unsealMatch && !unseal) {
|
||||
unseal = unsealMatch[1];
|
||||
}
|
||||
var rootMatch = output.match(/Root Token: (.+)$/m);
|
||||
if (rootMatch && !root) {
|
||||
root = rootMatch[1];
|
||||
}
|
||||
if (root && unseal && !written) {
|
||||
fs.writeFile(
|
||||
path.join(process.cwd(), 'tests/helpers/vault-keys.js'),
|
||||
`export default ${JSON.stringify({ unseal, root }, null, 2)}`,
|
||||
err => {
|
||||
if (err) throw err;
|
||||
}
|
||||
);
|
||||
written = true;
|
||||
console.log('VAULT SERVER READY');
|
||||
}
|
||||
});
|
||||
try {
|
||||
if (process.argv[2] === '--browserstack') {
|
||||
await run('ember', ['browserstack:connect']);
|
||||
try {
|
||||
await run('ember', ['test', '-f=secrets/secret/create', '-c', 'testem.browserstack.js']);
|
||||
|
||||
var pidFile = 'vault-ui-integration-server.pid';
|
||||
process.on('SIGINT', function() {
|
||||
vault.kill('SIGINT');
|
||||
process.exit();
|
||||
});
|
||||
process.on('exit', function() {
|
||||
vault.kill('SIGINT');
|
||||
});
|
||||
|
||||
fs.writeFile(pidFile, process.pid, err => {
|
||||
if (err) throw err;
|
||||
console.log('The file has been saved!');
|
||||
});
|
||||
console.log('success');
|
||||
process.exit(0);
|
||||
} finally {
|
||||
if (process.env.CI === 'true') {
|
||||
await run('ember', ['browserstack:results']);
|
||||
}
|
||||
await run('ember', ['browserstack:disconnect']);
|
||||
}
|
||||
} else {
|
||||
await run('ember', ['test', ...process.argv.slice(2)]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
process.exit(0);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
process.exit(0);
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/* 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`
|
||||
<h5 class="title is-5">Empty State</h5>
|
||||
<EmptyState @title={{title}} @message={{message}} />
|
||||
`,
|
||||
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`
|
||||
<h5 class="title is-5">Empty State</h5>
|
||||
<EmptyState @title={{title}} @message={{message}}>
|
||||
<DocLink @path="/docs/secrets/kv/kv-v2.html">Learn about KV v2</DocLink>
|
||||
</EmptyState>
|
||||
`,
|
||||
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}
|
||||
);
|
|
@ -1,4 +1,3 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import { storiesOf } from '@storybook/ember';
|
||||
import notes from './search-select.md';
|
||||
|
@ -13,13 +12,13 @@ storiesOf('SearchSelect/', module)
|
|||
.add(`SearchSelect`, () => ({
|
||||
template: hbs`
|
||||
<h5 class="title is-5">Search Select</h5>
|
||||
<SearchSelect
|
||||
@id="groups"
|
||||
@models={{models}}
|
||||
@onChange={{onChange}}
|
||||
<SearchSelect
|
||||
@id="groups"
|
||||
@models={{models}}
|
||||
@onChange={{onChange}}
|
||||
@inputValue={{inputValue}}
|
||||
@label={{label}}
|
||||
@fallbackComponent="string-list"
|
||||
@fallbackComponent="string-list"
|
||||
@staticOptions={{staticOptions}}/>
|
||||
`,
|
||||
context: {
|
||||
|
|
|
@ -18,9 +18,6 @@ const config = {
|
|||
].filter(Boolean),
|
||||
},
|
||||
},
|
||||
on_exit:
|
||||
'[ -e ../../vault-ui-integration-server.pid ] && node ../../scripts/start-vault.js `cat ../../vault-ui-integration-server.pid`; [ -e ../../vault-ui-integration-server.pid ] && rm ../../vault-ui-integration-server.pid',
|
||||
|
||||
proxies: {
|
||||
'/v1': {
|
||||
target: 'http://localhost:9200',
|
||||
|
|
|
@ -171,10 +171,8 @@ module('Acceptance | Enterprise | KMIP secrets', function(hooks) {
|
|||
`/vault/secrets/${path}/kmip/scopes/${scope}/roles/${role}`,
|
||||
'cancel navigates to role show'
|
||||
);
|
||||
await rolesPage
|
||||
.detailDelete()
|
||||
.delete()
|
||||
.confirmDelete();
|
||||
await rolesPage.delete().confirmDelete();
|
||||
|
||||
assert.equal(
|
||||
currentURL(),
|
||||
`/vault/secrets/${path}/kmip/scopes/${scope}/roles`,
|
||||
|
@ -209,8 +207,7 @@ module('Acceptance | Enterprise | KMIP secrets', function(hooks) {
|
|||
await credentialsPage.visit({ backend: path, scope, role });
|
||||
// revoke the credentials
|
||||
await credentialsPage.listItemLinks.objectAt(0).menuToggle();
|
||||
await credentialsPage.delete();
|
||||
await credentialsPage.confirmDelete();
|
||||
await credentialsPage.delete().confirmDelete();
|
||||
assert.equal(credentialsPage.listItemLinks.length, 0, 'renders no credentials');
|
||||
assert.ok(credentialsPage.isEmpty, 'renders empty');
|
||||
});
|
||||
|
@ -218,10 +215,7 @@ module('Acceptance | Enterprise | KMIP secrets', function(hooks) {
|
|||
test('it can revoke from the credentials show page', async function(assert) {
|
||||
let { path, scope, role, serial } = await generateCreds();
|
||||
await credentialsPage.visitDetail({ backend: path, scope, role, serial });
|
||||
await credentialsPage
|
||||
.detailRevoke()
|
||||
.delete()
|
||||
.confirmDelete();
|
||||
await credentialsPage.delete().confirmDelete();
|
||||
|
||||
assert.equal(
|
||||
currentURL(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { click, currentRouteName, currentURL, visit } from '@ember/test-helpers';
|
||||
import { click } from '@ember/test-helpers';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import { create } from 'ember-cli-page-object';
|
||||
|
|
|
@ -25,7 +25,6 @@ module('Acceptance | secrets/secret/create', function(hooks) {
|
|||
|
||||
hooks.beforeEach(async function() {
|
||||
this.server = apiStub({ usePassthrough: true });
|
||||
await logout.visit();
|
||||
return authPage.login();
|
||||
});
|
||||
|
||||
|
@ -215,7 +214,6 @@ module('Acceptance | secrets/secret/create', function(hooks) {
|
|||
await writeSecret(backend, 'secret', 'foo', 'bar');
|
||||
assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'redirects to the show page');
|
||||
assert.ok(showPage.editIsPresent, 'shows the edit button');
|
||||
await logout.visit();
|
||||
});
|
||||
|
||||
test('version 2 with restricted policy still allows edit', async function(assert) {
|
||||
|
@ -247,7 +245,6 @@ module('Acceptance | secrets/secret/create', function(hooks) {
|
|||
|
||||
assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'redirects to the show page');
|
||||
assert.ok(showPage.editIsPresent, 'shows the edit button');
|
||||
await logout.visit();
|
||||
});
|
||||
|
||||
test('paths are properly encoded', async function(assert) {
|
||||
|
@ -389,7 +386,6 @@ module('Acceptance | secrets/secret/create', function(hooks) {
|
|||
|
||||
await editPage.editSecret('bar', 'baz');
|
||||
assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'redirects to the show page');
|
||||
await logout.visit();
|
||||
});
|
||||
|
||||
test('write without read: version 2 with metadata read', async function(assert) {
|
||||
|
@ -409,7 +405,6 @@ module('Acceptance | secrets/secret/create', function(hooks) {
|
|||
|
||||
await editPage.editSecret('bar', 'baz');
|
||||
assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'redirects to the show page');
|
||||
await logout.visit();
|
||||
});
|
||||
|
||||
test('write without read: version 1', async function(assert) {
|
||||
|
@ -428,6 +423,5 @@ module('Acceptance | secrets/secret/create', function(hooks) {
|
|||
|
||||
await editPage.editSecret('bar', 'baz');
|
||||
assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'redirects to the show page');
|
||||
await logout.visit();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -248,7 +248,7 @@ module('Acceptance | transit', function(hooks) {
|
|||
// wait for capabilities
|
||||
await settled();
|
||||
assert.dom('[data-test-transit-key-version-row]').exists({ count: 1 }, `${name}: only one key version`);
|
||||
await click('[data-test-confirm-action-trigger');
|
||||
await click('[data-test-confirm-action-trigger]');
|
||||
await click('[data-test-confirm-button]');
|
||||
// wait for rotate call
|
||||
await settled();
|
||||
|
|
|
@ -14,12 +14,14 @@ import form from '../../pages/components/auth-jwt';
|
|||
import { ERROR_WINDOW_CLOSED, ERROR_MISSING_PARAMS } from 'vault/components/auth-jwt';
|
||||
|
||||
const component = create(form);
|
||||
const windows = [];
|
||||
const fakeWindow = EmberObject.extend(Evented, {
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.__proto__.on('close', () => {
|
||||
this.on('close', () => {
|
||||
this.set('closed', true);
|
||||
});
|
||||
windows.push(this);
|
||||
},
|
||||
screen: computed(function() {
|
||||
return {
|
||||
|
@ -41,7 +43,7 @@ fakeWindow.reopen({
|
|||
},
|
||||
|
||||
close() {
|
||||
fakeWindow.proto().trigger('close');
|
||||
windows.forEach(w => w.trigger('close'));
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -71,14 +71,14 @@ module('Integration | Component | edit form kmip role', function(hooks) {
|
|||
this.set('model', model);
|
||||
await render(hbs`<EditFormKmipRole @model={{model}} />`);
|
||||
|
||||
assert.dom('[data-test-input="operationAll"').isChecked('sets operationAll');
|
||||
assert.dom('[data-test-input="operationAll"]').isChecked('sets operationAll');
|
||||
});
|
||||
|
||||
test('it renders: operationAll', async function(assert) {
|
||||
let model = createModel({ operationAll: true });
|
||||
this.set('model', model);
|
||||
await render(hbs`<EditFormKmipRole @model={{model}} />`);
|
||||
assert.dom('[data-test-input="operationAll"').isChecked('sets operationAll');
|
||||
assert.dom('[data-test-input="operationAll"]').isChecked('sets operationAll');
|
||||
});
|
||||
|
||||
test('it renders: operationNone', async function(assert) {
|
||||
|
@ -95,7 +95,7 @@ module('Integration | Component | edit form kmip role', function(hooks) {
|
|||
await render(hbs`<EditFormKmipRole @model={{model}} />`);
|
||||
|
||||
assert.dom('[data-test-input="operationNone"]').isChecked('sets operationNone');
|
||||
assert.dom('[data-test-input="operationAll"').isNotChecked('sets operationAll');
|
||||
assert.dom('[data-test-input="operationAll"]').isNotChecked('sets operationAll');
|
||||
});
|
||||
|
||||
let savingTests = [
|
||||
|
|
|
@ -8,7 +8,7 @@ module('Integration | Component | toolbar-link', function(hooks) {
|
|||
setupRenderingTest(hooks);
|
||||
|
||||
test('it renders', async function(assert) {
|
||||
await render(hbs`<ToolbarLink @params="/secrets">Link</ToolbarLink>`);
|
||||
await render(hbs`<ToolbarLink @params={{array '/secrets'}}>Link</ToolbarLink>`);
|
||||
|
||||
assert.equal(this.element.textContent.trim(), 'Link');
|
||||
assert.ok(isPresent('.toolbar-link'));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue