mirror of https://github.com/status-im/consul.git
ui: UI Release Merge (ui-staging merge) (#6527)
## HTTPAdapter (#5637) ## Ember upgrade 2.18 > 3.12 (#6448) ### Proxies can no longer get away with not calling _super This means that we can't use create anymore to define dynamic methods. Therefore we dynamically make 2 extended Proxies on demand, and then create from those. Therefore we can call _super in the init method of the extended Proxies. ### We aren't allowed to reset a service anymore We never actually need to now anyway, this is a remnant of the refactor from browser based confirmations. We fix it as simply as possible here but will revisit and remove the old browser confirm functionality at a later date ### Revert classes to use ES5 style to workaround babel transp. probs Using a mixture of ES6 classes (and hence super) and arrow functions means that when babel transpiles the arrow functions down to ES5, a reference to this is moved before the call to super, hence causing a js error. Furthermore, we the testing environment no longer lets use use apply/call on the constructor. These errors only manifests during testing (only in the testing environment), the application itself runs fine with no problems without this change. Using ES5 style class definitions give us freedom to do all of the above without causing any errors, so we reverted these classes back to ES5 class definitions ### Skip test that seems to have changed due to a change in RSVP timing This test tests a usecase/area of the API that will probably never ever be used, it was more testing out the API. We've skipped the test for now as this doesn't affect the application itself, but left a note to come back here later to investigate further ### Remove enumerableContentDidChange Initial testing looks like we don't need to call this function anymore, the function no longer exists ### Rework Changeset.isSaving to take into account new ember APIs Setting/hanging a computedProperty of an instantiated object no longer works. Move to setting it on the prototype/class definition instead ### Change how we detect whether something requires listening New ember API's have changed how you can detect whether something is a computedProperty or not. It's not immediately clear if its even possible now. Therefore we change how we detect whether something should be listened to or not by just looking for presence of `addEventListener` ### Potentially temporary change of ci test scripts to ensure deps exist All our tooling scripts run through a Makefile (for people familiar with only using those), which then call yarn scripts which can be called independently (for people familar with only using yarn). The Makefile targets always check to make sure all the dependencies are installed before running anything that requires them (building, testing etc). The CI scripts/targets didn't follow this same route and called the yarn scripts directly (usually CI builds a cache of the dependencies first). For some reason this cache isn't doing what it usually does, and it looks as though, in CI, ember isn't installed. This commit makes the CI scripts consistently use the same method as all of the other tooling scripts (Makefile target > Install Deps if required > call yarn script). This should install the dependencies if for some reason the CI cache building doesn't complete/isn't successful. Potentially this commit may be reverted if, the root of the problem is elsewhere, although consistency is always good, so it might be a good idea to leave this commit as is even if we need to debug and fix things elsewhere. ### Make test-parallel consistent with the rest of the tooling scripts As we are here making changes for CI purposes (making test-ci consistent), we spotted that test-parallel is also inconsistent and also the README manual instructions won't work without `ember` installed globally. This commit makes everything consistent and changes the manual instructions to use the local ember instance that gets installed via yarn ### Re-wrangle catchable to fit with new ember 3.12 APIs In the upgrade from ember 3.8 > 3.12 the public interfaces for ComputedProperties have changed slightly. `meta` is no longer a public property of ComputedProperty but of a ComputedDecoratorImpl mixin instead.7e4ba1096e/packages/%40ember/-internals/metal/lib/computed.ts (L725)
There seems to be no way, by just using publically available methods, to replicate this behaviour so that we can create our own 'ComputedProperty` factory via injecting the ComputedProperty class as we did previously.3f333bada1/ui-v2/app/utils/computed/factory.js (L1-L18)
Instead we dynamically hang our `Catchable` `catch` method off the instantiated ComputedProperty. In doing it like this `ComputedProperty` has already has its `meta` method mixed in so we don't have to manually mix it in ourselves (which doesn't seem possible) This functionality is only used during our work in trying to ensure our EventSource/BlockingQuery work was as 'ember-like' as possible (i.e. using the traditional Route.model hooks and ember-like Controller properties). Our ongoing/upcoming work on a componentized approach to data a.k.a `<DataSource />` means we will be able to remove the majority of the code involved here now that it seems to be under an amount of flux in ember. ### Build bindata_assetfs.go with new UI changes
This commit is contained in:
parent
2eaece10a7
commit
b3b32dc0f6
|
@ -447,7 +447,7 @@ jobs:
|
|||
- checkout
|
||||
- restore_cache:
|
||||
key: *YARN_CACHE_KEY
|
||||
- run: cd ui-v2 && yarn build-ci --output-path=dist
|
||||
- run: cd ui-v2 && make build-ci
|
||||
|
||||
# saves the build to a workspace to be passed to a downstream job
|
||||
- persist_to_workspace:
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1,21 @@
|
|||
app/utils/dom/event-target/event-target-shim/event.js
|
||||
# unconventional js
|
||||
/blueprints/*/files/
|
||||
/vendor/
|
||||
|
||||
# compiled output
|
||||
/dist/
|
||||
/tmp/
|
||||
|
||||
# dependencies
|
||||
/bower_components/
|
||||
/node_modules/
|
||||
|
||||
# misc
|
||||
/coverage/
|
||||
!.*
|
||||
|
||||
# ember-try
|
||||
/.node_modules.ember-try/
|
||||
/bower.json.ember-try
|
||||
/package.json.ember-try
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2017,
|
||||
sourceType: 'module',
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true
|
||||
}
|
||||
ecmaVersion: 2018,
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['ember'],
|
||||
extends: ['eslint:recommended', 'plugin:ember/recommended'],
|
||||
|
@ -13,29 +10,38 @@ module.exports = {
|
|||
browser: true,
|
||||
},
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { args: 'none' }]
|
||||
'no-unused-vars': ['error', { args: 'none' }],
|
||||
'ember/no-new-mixins': ['warn']
|
||||
},
|
||||
overrides: [
|
||||
// node files
|
||||
{
|
||||
files: ['testem.js', 'ember-cli-build.js', 'config/**/*.js'],
|
||||
files: [
|
||||
'.eslintrc.js',
|
||||
'.dev.eslintrc.js',
|
||||
'.template-lintrc.js',
|
||||
'ember-cli-build.js',
|
||||
'testem.js',
|
||||
'blueprints/*/index.js',
|
||||
'config/**/*.js',
|
||||
'lib/*/index.js',
|
||||
'server/**/*.js'
|
||||
],
|
||||
parserOptions: {
|
||||
sourceType: 'script',
|
||||
ecmaVersion: 2015,
|
||||
sourceType: 'script'
|
||||
},
|
||||
env: {
|
||||
browser: false,
|
||||
node: true,
|
||||
node: true
|
||||
},
|
||||
},
|
||||
plugins: ['node'],
|
||||
rules: Object.assign({}, require('eslint-plugin-node').configs.recommended.rules, {
|
||||
// add your custom rules and overrides for node files here
|
||||
|
||||
// test files
|
||||
{
|
||||
files: ['tests/**/*.js'],
|
||||
excludedFiles: ['tests/dummy/**/*.js'],
|
||||
env: {
|
||||
embertest: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
// this can be removed once the following is fixed
|
||||
// https://github.com/mysticatea/eslint-plugin-node/issues/77
|
||||
'node/no-unpublished-require': 'off'
|
||||
})
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
/dist
|
||||
|
||||
/tmp
|
||||
/node_modules
|
||||
|
||||
/coverage/*
|
||||
/npm-debug.log*
|
||||
/yarn-error.log
|
||||
/testem.log
|
||||
|
||||
/public/consul-api-double
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist/
|
||||
/tmp/
|
||||
|
||||
# dependencies
|
||||
/bower_components/
|
||||
/node_modules/
|
||||
|
||||
# misc
|
||||
/.env*
|
||||
/.pnp*
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage/
|
||||
/libpeerconnection.log
|
||||
/npm-debug.log*
|
||||
/testem.log
|
||||
/yarn-error.log
|
||||
|
||||
# ember-try
|
||||
/.node_modules.ember-try/
|
||||
/bower.json.ember-try
|
||||
/package.json.ember-try
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
extends: 'recommended',
|
||||
rules: {
|
||||
'no-partial': false,
|
||||
|
||||
'no-invalid-interactive': false,
|
||||
'simple-unless': false,
|
||||
|
||||
'self-closing-void-elements': false,
|
||||
'no-unnecessary-concat': false,
|
||||
'no-nested-interactive': false,
|
||||
|
||||
'block-indentation': false,
|
||||
'quotes': false,
|
||||
|
||||
'no-inline-styles': false,
|
||||
'no-triple-curlies': false,
|
||||
'no-unused-block-params': false,
|
||||
'style-concatenation': false,
|
||||
'link-rel-noopener': false
|
||||
},
|
||||
};
|
|
@ -21,7 +21,7 @@ build-staging: deps
|
|||
yarn run build:staging
|
||||
|
||||
build-ci: deps
|
||||
yarn run build-ci --output-path=dist
|
||||
yarn run build:ci --output-path=dist
|
||||
|
||||
build: deps
|
||||
yarn run build
|
||||
|
@ -39,10 +39,10 @@ test-view: deps
|
|||
yarn run test:view
|
||||
|
||||
test-parallel: deps
|
||||
yarn test-parallel
|
||||
yarn run test:parallel
|
||||
|
||||
lint: deps
|
||||
yarn run lint:js
|
||||
yarn run lint:hbs && yarn run lint:js
|
||||
|
||||
format: deps
|
||||
yarn run format:js
|
||||
|
|
|
@ -17,6 +17,8 @@ You will need the following things properly installed on your computer.
|
|||
* `cd ui-v2`
|
||||
* `yarn install`
|
||||
|
||||
All tooling scripts below primarily use `make` which in turn call node package scripts.
|
||||
|
||||
## Running / Development
|
||||
|
||||
The source code comes with a small server that runs enough of the consul API
|
||||
|
@ -61,6 +63,19 @@ Please note: You do not need to run `make start-api`/`yarn run start:api` to run
|
|||
* `make test` or `yarn run test`
|
||||
* `make test-view` or `yarn run test:view` to view the tests running in Chrome
|
||||
|
||||
### Linting
|
||||
|
||||
`make lint` currently runs linting on the majority of js files and hbs files (using `ember-template-lint`).
|
||||
|
||||
See `.eslintrc.js` and `.eslintignore` for specific configuration.
|
||||
|
||||
### Building
|
||||
|
||||
* `make build` builds the UI for production usage (env=production)
|
||||
* `make build-ci` builds the UI for CI/test usage (env=test)
|
||||
|
||||
Static files are built into ./dist
|
||||
|
||||
#### Running Tests in Parallel
|
||||
Alternatively, `ember-exam` can be used to split the tests across multiple browser instances for faster results. Most options are the same as `ember test`. To see a full list of options, run `ember exam --help`.
|
||||
|
||||
|
@ -68,12 +83,12 @@ Alternatively, `ember-exam` can be used to split the tests across multiple brows
|
|||
|
||||
To quickly run the tests across 4 parallel browser instances:
|
||||
```sh
|
||||
yarn test-parallel
|
||||
make test-parallel
|
||||
```
|
||||
|
||||
To run manually:
|
||||
```sh
|
||||
$ EMBER_EXAM_PARALLEL=true ember exam --split <num> --parallel
|
||||
$ EMBER_EXAM_PARALLEL=true ./node_modules/.bin/ember exam --split <num> --parallel
|
||||
```
|
||||
|
||||
More ways to split tests can be found in the [ember-exam README.md](https://github.com/trentmwillis/ember-exam/blob/master/README.md).
|
||||
More ways to split tests can be found in the [ember-exam README.md](https://github.com/trentmwillis/ember-exam/blob/master/README.md).
|
||||
|
|
|
@ -1,147 +1,66 @@
|
|||
import Adapter, {
|
||||
REQUEST_CREATE,
|
||||
REQUEST_UPDATE,
|
||||
REQUEST_DELETE,
|
||||
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
|
||||
} from './application';
|
||||
import EmberError from '@ember/error';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/acl';
|
||||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
import { SLUG_KEY } from 'consul-ui/models/acl';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { PUT as HTTP_PUT } from 'consul-ui/utils/http/method';
|
||||
import { OK as HTTP_OK, UNAUTHORIZED as HTTP_UNAUTHORIZED } from 'consul-ui/utils/http/status';
|
||||
|
||||
import makeAttrable from 'consul-ui/utils/makeAttrable';
|
||||
const REQUEST_CLONE = 'cloneRecord';
|
||||
export default Adapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
requestForQuery: function(request, { dc, index }) {
|
||||
// https://www.consul.io/api/acl.html#list-acls
|
||||
return this.appendURL('acl/list', [], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/acl/list?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
// https://www.consul.io/api/acl.html#read-acl-token
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('acl/info', [query.id], this.cleanQuery(query));
|
||||
// https://www.consul.io/api/acl.html#read-acl-token
|
||||
return request`
|
||||
GET /v1/acl/info/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForCreateRecord: function(modelName, snapshot) {
|
||||
requestForCreateRecord: function(request, serialized, data) {
|
||||
// https://www.consul.io/api/acl.html#create-acl-token
|
||||
return this.appendURL('acl/create', [], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
return request`
|
||||
PUT /v1/acl/create?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForUpdateRecord: function(id, modelName, snapshot) {
|
||||
// the id is in the payload, don't add it in here
|
||||
requestForUpdateRecord: function(request, serialized, data) {
|
||||
// the id is in the data, don't add it into the URL
|
||||
// https://www.consul.io/api/acl.html#update-acl-token
|
||||
return this.appendURL('acl/update', [], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
return request`
|
||||
PUT /v1/acl/update?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForDeleteRecord: function(id, modelName, snapshot) {
|
||||
requestForDeleteRecord: function(request, serialized, data) {
|
||||
// https://www.consul.io/api/acl.html#delete-acl-token
|
||||
return this.appendURL('acl/destroy', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
return request`
|
||||
PUT /v1/acl/destroy/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
`;
|
||||
},
|
||||
urlForCloneRecord: function(modelName, snapshot) {
|
||||
requestForCloneRecord: function(request, serialized, data) {
|
||||
// https://www.consul.io/api/acl.html#clone-acl-token
|
||||
return this.appendURL('acl/clone', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
return request`
|
||||
PUT /v1/acl/clone/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
`;
|
||||
},
|
||||
urlForRequest: function({ type, snapshot, requestType }) {
|
||||
switch (requestType) {
|
||||
case 'cloneRecord':
|
||||
return this.urlForCloneRecord(type.modelName, snapshot);
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
clone: function(store, modelClass, id, snapshot) {
|
||||
const params = {
|
||||
store: store,
|
||||
type: modelClass,
|
||||
id: id,
|
||||
snapshot: snapshot,
|
||||
requestType: 'cloneRecord',
|
||||
};
|
||||
// _requestFor is private... but these methods aren't, until they disappear..
|
||||
const request = {
|
||||
method: this.methodForRequest(params),
|
||||
url: this.urlForRequest(params),
|
||||
headers: this.headersForRequest(params),
|
||||
data: this.dataForRequest(params),
|
||||
};
|
||||
// TODO: private..
|
||||
return this._makeRequest(request);
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
const data = this._super(...arguments);
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
case REQUEST_CREATE:
|
||||
return data.acl;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
methodForRequest: function(params) {
|
||||
switch (params.requestType) {
|
||||
case REQUEST_DELETE:
|
||||
case REQUEST_CREATE:
|
||||
case REQUEST_CLONE:
|
||||
return HTTP_PUT;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
isCreateRecord: function(url, method) {
|
||||
return (
|
||||
url.pathname ===
|
||||
this.parseURL(this.urlForCreateRecord('acl', makeAttrable({ [DATACENTER_KEY]: '' }))).pathname
|
||||
clone: function(store, type, id, snapshot) {
|
||||
return this.request(
|
||||
function(adapter, request, serialized, unserialized) {
|
||||
return adapter.requestForCloneRecord(request, serialized, unserialized);
|
||||
},
|
||||
function(serializer, respond, serialized, unserialized) {
|
||||
return serializer.respondForCreateRecord(respond, serialized, unserialized);
|
||||
},
|
||||
snapshot,
|
||||
type.modelName
|
||||
);
|
||||
},
|
||||
isCloneRecord: function(url, method) {
|
||||
return (
|
||||
url.pathname ===
|
||||
this.parseURL(
|
||||
this.urlForCloneRecord(
|
||||
'acl',
|
||||
makeAttrable({ [SLUG_KEY]: this.slugFromURL(url), [DATACENTER_KEY]: '' })
|
||||
)
|
||||
).pathname
|
||||
);
|
||||
},
|
||||
isUpdateRecord: function(url, method) {
|
||||
return (
|
||||
url.pathname ===
|
||||
this.parseURL(this.urlForUpdateRecord(null, 'acl', makeAttrable({ [DATACENTER_KEY]: '' })))
|
||||
.pathname
|
||||
);
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
const method = requestData.method;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case response === true:
|
||||
response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
case this.isQueryRecord(url):
|
||||
response = this.handleSingleResponse(url, response[0], PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
case this.isUpdateRecord(url, method):
|
||||
case this.isCreateRecord(url, method):
|
||||
case this.isCloneRecord(url, method):
|
||||
response = this.handleSingleResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
} else if (status === HTTP_UNAUTHORIZED) {
|
||||
const e = new EmberError();
|
||||
e.code = status;
|
||||
e.message = payload;
|
||||
throw e;
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,182 +1,44 @@
|
|||
import Adapter from 'ember-data/adapters/rest';
|
||||
import { AbortError } from 'ember-data/adapters/errors';
|
||||
import Adapter from './http';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import URL from 'url';
|
||||
import createURL from 'consul-ui/utils/createURL';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { HEADERS_SYMBOL as HTTP_HEADERS_SYMBOL } from 'consul-ui/utils/http/consul';
|
||||
|
||||
export const REQUEST_CREATE = 'createRecord';
|
||||
export const REQUEST_READ = 'queryRecord';
|
||||
export const REQUEST_UPDATE = 'updateRecord';
|
||||
export const REQUEST_DELETE = 'deleteRecord';
|
||||
// export const REQUEST_READ_MULTIPLE = 'query';
|
||||
|
||||
export const DATACENTER_QUERY_PARAM = 'dc';
|
||||
|
||||
export default Adapter.extend({
|
||||
namespace: 'v1',
|
||||
repo: service('settings'),
|
||||
client: service('client/http'),
|
||||
manageConnection: function(options) {
|
||||
const client = get(this, 'client');
|
||||
const complete = options.complete;
|
||||
const beforeSend = options.beforeSend;
|
||||
options.beforeSend = function(xhr) {
|
||||
if (typeof beforeSend === 'function') {
|
||||
beforeSend(...arguments);
|
||||
}
|
||||
options.id = client.request(options, xhr);
|
||||
};
|
||||
options.complete = function(xhr, textStatus) {
|
||||
client.complete(options.id);
|
||||
if (typeof complete === 'function') {
|
||||
complete(...arguments);
|
||||
}
|
||||
};
|
||||
return options;
|
||||
},
|
||||
_ajaxRequest: function(options) {
|
||||
return this._super(this.manageConnection(options));
|
||||
},
|
||||
queryRecord: function() {
|
||||
return this._super(...arguments).catch(function(e) {
|
||||
if (e instanceof AbortError) {
|
||||
e.errors[0].status = '0';
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
},
|
||||
query: function() {
|
||||
return this._super(...arguments).catch(function(e) {
|
||||
if (e instanceof AbortError) {
|
||||
e.errors[0].status = '0';
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
},
|
||||
headersForRequest: function(params) {
|
||||
return {
|
||||
...this.get('repo').findHeaders(),
|
||||
...this._super(...arguments),
|
||||
};
|
||||
},
|
||||
handleResponse: function(status, headers, response, requestData) {
|
||||
// The ember-data RESTAdapter drops the headers after this call,
|
||||
// and there is no where else to get to these
|
||||
// save them to response[HTTP_HEADERS_SYMBOL] for the moment
|
||||
// so we can save them as meta in the serializer...
|
||||
if (
|
||||
(typeof response == 'object' && response.constructor == Object) ||
|
||||
Array.isArray(response)
|
||||
) {
|
||||
// lowercase everything incase we get browser inconsistencies
|
||||
const lower = {};
|
||||
Object.keys(headers).forEach(function(key) {
|
||||
lower[key.toLowerCase()] = headers[key];
|
||||
// TODO: kinda protected for the moment
|
||||
// decide where this should go either read/write from http
|
||||
// should somehow use this or vice versa
|
||||
request: function(req, resp, obj, modelName) {
|
||||
const client = this.client;
|
||||
const store = this.store;
|
||||
const adapter = this;
|
||||
|
||||
let unserialized, serialized;
|
||||
const serializer = store.serializerFor(modelName);
|
||||
// workable way to decide whether this is a snapshot
|
||||
// Snapshot is private so we can't do instanceof here
|
||||
if (obj.constructor.name === 'Snapshot') {
|
||||
unserialized = obj.attributes();
|
||||
serialized = serializer.serialize(obj, {});
|
||||
} else {
|
||||
unserialized = obj;
|
||||
serialized = unserialized;
|
||||
}
|
||||
|
||||
return client
|
||||
.request(function(request) {
|
||||
return req(adapter, request, serialized, unserialized);
|
||||
})
|
||||
.catch(function(e) {
|
||||
return adapter.error(e);
|
||||
})
|
||||
.then(function(respond) {
|
||||
// TODO: When HTTPAdapter:responder changes, this will also need to change
|
||||
return resp(serializer, respond, serialized, unserialized);
|
||||
});
|
||||
response[HTTP_HEADERS_SYMBOL] = lower;
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
},
|
||||
handleBooleanResponse: function(url, response, primary, slug) {
|
||||
return {
|
||||
// consider a check for a boolean, also for future me,
|
||||
// response[slug] // this will forever be null, response should be boolean
|
||||
[primary]: this.uidForURL(url /* response[slug]*/),
|
||||
};
|
||||
},
|
||||
// could always consider an extra 'dc' arg on the end here?
|
||||
handleSingleResponse: function(url, response, primary, slug, _dc) {
|
||||
const dc =
|
||||
typeof _dc !== 'undefined' ? _dc : url.searchParams.get(DATACENTER_QUERY_PARAM) || '';
|
||||
return {
|
||||
...response,
|
||||
...{
|
||||
[DATACENTER_KEY]: dc,
|
||||
[primary]: this.uidForURL(url, response[slug]),
|
||||
},
|
||||
};
|
||||
},
|
||||
handleBatchResponse: function(url, response, primary, slug) {
|
||||
const dc = url.searchParams.get(DATACENTER_QUERY_PARAM) || '';
|
||||
return response.map((item, i, arr) => {
|
||||
return this.handleSingleResponse(url, item, primary, slug, dc);
|
||||
});
|
||||
},
|
||||
cleanQuery: function(_query) {
|
||||
if (typeof _query.id !== 'undefined') {
|
||||
delete _query.id;
|
||||
}
|
||||
const query = { ..._query };
|
||||
if (typeof query.separator !== 'undefined') {
|
||||
delete query.separator;
|
||||
}
|
||||
if (typeof query.index !== 'undefined') {
|
||||
delete query.index;
|
||||
}
|
||||
delete _query[DATACENTER_QUERY_PARAM];
|
||||
return query;
|
||||
},
|
||||
isUpdateRecord: function(url, method) {
|
||||
return false;
|
||||
},
|
||||
isCreateRecord: function(url, method) {
|
||||
return false;
|
||||
},
|
||||
isQueryRecord: function(url, method) {
|
||||
// this is ONLY if ALL api's using it
|
||||
// follow the 'last part of the url is the id' rule
|
||||
const pathname = url.pathname
|
||||
.split('/') // unslashify
|
||||
// remove the last
|
||||
.slice(0, -1)
|
||||
// add and empty to ensure a trailing slash
|
||||
.concat([''])
|
||||
// slashify
|
||||
.join('/');
|
||||
// compare with empty id against empty id
|
||||
return pathname === this.parseURL(this.urlForQueryRecord({ id: '' })).pathname;
|
||||
},
|
||||
getHost: function() {
|
||||
return this.host || `${location.protocol}//${location.host}`;
|
||||
},
|
||||
slugFromURL: function(url, decode = decodeURIComponent) {
|
||||
// follow the 'last part of the url is the id' rule
|
||||
return decode(url.pathname.split('/').pop());
|
||||
},
|
||||
parseURL: function(str) {
|
||||
return new URL(str, this.getHost());
|
||||
},
|
||||
uidForURL: function(url, _slug = '', hash = JSON.stringify) {
|
||||
const dc = url.searchParams.get(DATACENTER_QUERY_PARAM) || '';
|
||||
const slug = _slug === '' ? this.slugFromURL(url) : _slug;
|
||||
if (dc.length < 1) {
|
||||
throw new Error('Unable to create unique id, missing datacenter');
|
||||
}
|
||||
if (slug.length < 1) {
|
||||
throw new Error('Unable to create unique id, missing slug');
|
||||
}
|
||||
// TODO: we could use a URL here? They are unique AND useful
|
||||
// but probably slower to create?
|
||||
return hash([dc, slug]);
|
||||
},
|
||||
|
||||
// appendURL in turn calls createURL
|
||||
// createURL ensures that all `parts` are URL encoded
|
||||
// and all `query` values are URL encoded
|
||||
|
||||
// `this.buildURL()` with no arguments will give us `${host}/${namespace}`
|
||||
// `path` is the user configurable 'urlsafe' string to append on `buildURL`
|
||||
// `parts` is an array of possibly non 'urlsafe parts' to be encoded and
|
||||
// appended onto the url
|
||||
// `query` will populate the query string. Again the values of which will be
|
||||
// url encoded
|
||||
|
||||
appendURL: function(path, parts = [], query = {}) {
|
||||
// path can be a string or an array of parts that will be slash joined
|
||||
return createURL([this.buildURL()].concat(path), parts, query);
|
||||
// TODO: Potentially add specific serializer errors here
|
||||
// .catch(function(e) {
|
||||
// return Promise.reject(e);
|
||||
// });
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,23 +1,10 @@
|
|||
import ApplicationAdapter from './application';
|
||||
import Adapter from './application';
|
||||
export default Adapter.extend({
|
||||
requestForQuery: function(request, { dc, index }) {
|
||||
return request`
|
||||
GET /v1/coordinate/nodes?${{ dc }}
|
||||
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/coordinate';
|
||||
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
|
||||
export default ApplicationAdapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
// https://www.consul.io/api/coordinate.html#read-lan-coordinates-for-all-nodes
|
||||
return this.appendURL('coordinate/nodes', [], this.cleanQuery(query));
|
||||
},
|
||||
isQueryRecord: function(url) {
|
||||
return true;
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import Adapter from './application';
|
||||
|
||||
export default Adapter.extend({
|
||||
urlForFindAll: function() {
|
||||
return this.appendURL('catalog/datacenters');
|
||||
requestForFindAll: function(request) {
|
||||
return request`
|
||||
GET /v1/catalog/datacenters
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
import Adapter from 'ember-data/adapter';
|
||||
import {
|
||||
AbortError,
|
||||
TimeoutError,
|
||||
ServerError,
|
||||
UnauthorizedError,
|
||||
ForbiddenError,
|
||||
NotFoundError,
|
||||
ConflictError,
|
||||
InvalidError,
|
||||
AdapterError,
|
||||
} from 'ember-data/adapters/errors';
|
||||
|
||||
// TODO: This is a little skeleton cb function
|
||||
// is to be replaced soon with something slightly more involved
|
||||
const responder = function(response) {
|
||||
return response;
|
||||
};
|
||||
const read = function(adapter, serializer, client, type, query) {
|
||||
return client
|
||||
.request(function(request) {
|
||||
return adapter[`requestFor${type}`](request, query);
|
||||
})
|
||||
.catch(function(e) {
|
||||
return adapter.error(e);
|
||||
})
|
||||
.then(function(response) {
|
||||
return serializer[`respondFor${type}`](responder(response), query);
|
||||
});
|
||||
// TODO: Potentially add specific serializer errors here
|
||||
// .catch(function(e) {
|
||||
// return Promise.reject(e);
|
||||
// });
|
||||
};
|
||||
const write = function(adapter, serializer, client, type, snapshot) {
|
||||
const unserialized = snapshot.attributes();
|
||||
const serialized = serializer.serialize(snapshot, {});
|
||||
return client
|
||||
.request(function(request) {
|
||||
return adapter[`requestFor${type}`](request, serialized, unserialized);
|
||||
})
|
||||
.catch(function(e) {
|
||||
return adapter.error(e);
|
||||
})
|
||||
.then(function(response) {
|
||||
return serializer[`respondFor${type}`](responder(response), serialized, unserialized);
|
||||
});
|
||||
// TODO: Potentially add specific serializer errors here
|
||||
// .catch(function(e) {
|
||||
// return Promise.reject(e);
|
||||
// });
|
||||
};
|
||||
export default Adapter.extend({
|
||||
error: function(err) {
|
||||
const errors = [
|
||||
{
|
||||
status: `${err.statusCode}`,
|
||||
title: 'The backend responded with an error',
|
||||
detail: err.message,
|
||||
},
|
||||
];
|
||||
let error;
|
||||
const detailedMessage = '';
|
||||
try {
|
||||
switch (err.statusCode) {
|
||||
case 0:
|
||||
error = new AbortError();
|
||||
break;
|
||||
case 401:
|
||||
error = new UnauthorizedError(errors, detailedMessage);
|
||||
break;
|
||||
case 403:
|
||||
error = new ForbiddenError(errors, detailedMessage);
|
||||
break;
|
||||
case 404:
|
||||
error = new NotFoundError(errors, detailedMessage);
|
||||
break;
|
||||
case 408:
|
||||
error = new TimeoutError();
|
||||
break;
|
||||
case 409:
|
||||
error = new ConflictError(errors, detailedMessage);
|
||||
break;
|
||||
case 422:
|
||||
error = new InvalidError(errors); //payload.errors
|
||||
break;
|
||||
default:
|
||||
if (err.statusCode >= 500) {
|
||||
error = new ServerError(errors, detailedMessage);
|
||||
} else {
|
||||
error = new AdapterError(errors, detailedMessage);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
throw error;
|
||||
},
|
||||
query: function(store, type, query) {
|
||||
return read(this, store.serializerFor(type.modelName), this.client, 'Query', query);
|
||||
},
|
||||
queryRecord: function(store, type, query) {
|
||||
return read(this, store.serializerFor(type.modelName), this.client, 'QueryRecord', query);
|
||||
},
|
||||
findAll: function(store, type) {
|
||||
return read(this, store.serializerFor(type.modelName), this.client, 'FindAll');
|
||||
},
|
||||
createRecord: function(store, type, snapshot) {
|
||||
return write(this, store.serializerFor(type.modelName), this.client, 'CreateRecord', snapshot);
|
||||
},
|
||||
updateRecord: function(store, type, snapshot) {
|
||||
return write(this, store.serializerFor(type.modelName), this.client, 'UpdateRecord', snapshot);
|
||||
},
|
||||
deleteRecord: function(store, type, snapshot) {
|
||||
return write(this, store.serializerFor(type.modelName), this.client, 'DeleteRecord', snapshot);
|
||||
},
|
||||
});
|
|
@ -1,80 +1,44 @@
|
|||
import Adapter, {
|
||||
REQUEST_CREATE,
|
||||
REQUEST_UPDATE,
|
||||
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
|
||||
} from './application';
|
||||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/intention';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
import { POST as HTTP_POST } from 'consul-ui/utils/http/method';
|
||||
import makeAttrable from 'consul-ui/utils/makeAttrable';
|
||||
import { SLUG_KEY } from 'consul-ui/models/intention';
|
||||
export default Adapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
return this.appendURL('connect/intentions', [], this.cleanQuery(query));
|
||||
requestForQuery: function(request, { dc, index, id }) {
|
||||
return request`
|
||||
GET /v1/connect/intentions?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('connect/intentions', [query.id], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/connect/intentions/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForCreateRecord: function(modelName, snapshot) {
|
||||
return this.appendURL('connect/intentions', [], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
requestForCreateRecord: function(request, serialized, data) {
|
||||
// TODO: need to make sure we remove dc
|
||||
return request`
|
||||
POST /v1/connect/intentions?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForUpdateRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('connect/intentions', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
requestForUpdateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/connect/intentions/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForDeleteRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('connect/intentions', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
},
|
||||
isUpdateRecord: function(url, method) {
|
||||
return (
|
||||
url.pathname ===
|
||||
this.parseURL(
|
||||
this.urlForUpdateRecord(null, 'intention', makeAttrable({ [DATACENTER_KEY]: '' }))
|
||||
).pathname
|
||||
);
|
||||
},
|
||||
isCreateRecord: function(url, method) {
|
||||
return (
|
||||
method.toUpperCase() === HTTP_POST &&
|
||||
url.pathname ===
|
||||
this.parseURL(this.urlForCreateRecord('intention', makeAttrable({ [DATACENTER_KEY]: '' })))
|
||||
.pathname
|
||||
);
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
const method = requestData.method;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case this.isQueryRecord(url, method):
|
||||
case this.isUpdateRecord(url, method):
|
||||
case this.isCreateRecord(url, method):
|
||||
// TODO: We just need to upgrade this (^^ sorry linter) entire API to
|
||||
// use a full request-like object
|
||||
response = this.handleSingleResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
const data = this._super(...arguments);
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
case REQUEST_CREATE:
|
||||
return data.intention;
|
||||
}
|
||||
return data;
|
||||
requestForDeleteRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
DELETE /v1/connect/intentions/${data[SLUG_KEY]}?${{
|
||||
[API_DATACENTER_KEY]: data[DATACENTER_KEY],
|
||||
}}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,150 +1,61 @@
|
|||
import Adapter, {
|
||||
REQUEST_CREATE,
|
||||
REQUEST_UPDATE,
|
||||
REQUEST_DELETE,
|
||||
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
|
||||
} from './application';
|
||||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
|
||||
import isFolder from 'consul-ui/utils/isFolder';
|
||||
import injectableRequestToJQueryAjaxHash from 'consul-ui/utils/injectableRequestToJQueryAjaxHash';
|
||||
import { typeOf } from '@ember/utils';
|
||||
import { get } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
import keyToArray from 'consul-ui/utils/keyToArray';
|
||||
import removeNull from 'consul-ui/utils/remove-null';
|
||||
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/kv';
|
||||
import { SLUG_KEY } from 'consul-ui/models/kv';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { PUT as HTTP_PUT, DELETE as HTTP_DELETE } from 'consul-ui/utils/http/method';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
|
||||
const API_KEYS_KEY = 'keys';
|
||||
const stringify = function(obj) {
|
||||
if (typeOf(obj) === 'string') {
|
||||
return obj;
|
||||
}
|
||||
return JSON.stringify(obj);
|
||||
};
|
||||
export default Adapter.extend({
|
||||
// There is no code path that can avoid the payload of a PUT request from
|
||||
// going via JSON.stringify.
|
||||
// Therefore a string payload of 'foobar' will always be encoded to '"foobar"'
|
||||
//
|
||||
// This means we have no other choice but rewriting the entire codepath or
|
||||
// overwriting the private `_requestToJQueryAjaxHash` method
|
||||
//
|
||||
// The `injectableRequestToJQueryAjaxHash` function makes the JSON object
|
||||
// injectable, meaning we can copy letter for letter the sourcecode of
|
||||
// `_requestToJQueryAjaxHash`, which means we can compare it with the original
|
||||
// private method within a test (`tests/unit/utils/injectableRequestToJQueryAjaxHash.js`).
|
||||
// This means, if `_requestToJQueryAjaxHash` changes between Ember versions
|
||||
// we will know about it
|
||||
requestForQuery: function(request, { dc, index, id, separator }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return request`
|
||||
GET /v1/kv/${keyToArray(id)}?${{ [API_KEYS_KEY]: null, dc, separator }}
|
||||
|
||||
_requestToJQueryAjaxHash: injectableRequestToJQueryAjaxHash({
|
||||
stringify: stringify,
|
||||
}),
|
||||
decoder: service('atob'),
|
||||
urlForQuery: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
// append keys here otherwise query.keys will add an '='
|
||||
return this.appendURL('kv', keyToArray(query.id), {
|
||||
...{
|
||||
[API_KEYS_KEY]: null,
|
||||
},
|
||||
...this.cleanQuery(query),
|
||||
});
|
||||
return request`
|
||||
GET /v1/kv/${keyToArray(id)}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
// TODO: Should we replace text/plain here with x-www-form-encoded?
|
||||
// See https://github.com/hashicorp/consul/issues/3804
|
||||
requestForCreateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/kv/${keyToArray(data[SLUG_KEY])}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
requestForUpdateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/kv/${keyToArray(data[SLUG_KEY])}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
requestForDeleteRecord: function(request, serialized, data) {
|
||||
let recurse;
|
||||
if (isFolder(data[SLUG_KEY])) {
|
||||
recurse = null;
|
||||
}
|
||||
return this.appendURL('kv', keyToArray(query.id), this.cleanQuery(query));
|
||||
},
|
||||
urlForCreateRecord: function(modelName, snapshot) {
|
||||
return this.appendURL('kv', keyToArray(snapshot.attr(SLUG_KEY)), {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
},
|
||||
urlForUpdateRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('kv', keyToArray(snapshot.attr(SLUG_KEY)), {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
},
|
||||
urlForDeleteRecord: function(id, modelName, snapshot) {
|
||||
const query = {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
};
|
||||
if (isFolder(snapshot.attr(SLUG_KEY))) {
|
||||
query.recurse = null;
|
||||
}
|
||||
return this.appendURL('kv', keyToArray(snapshot.attr(SLUG_KEY)), query);
|
||||
},
|
||||
slugFromURL: function(url) {
|
||||
// keys don't follow the 'last part of the url' rule as they contain slashes
|
||||
return decodeURIComponent(
|
||||
url.pathname
|
||||
.split('/')
|
||||
.splice(3)
|
||||
.join('/')
|
||||
);
|
||||
},
|
||||
isQueryRecord: function(url, method) {
|
||||
return !url.searchParams.has(API_KEYS_KEY);
|
||||
},
|
||||
handleBatchResponse: function(url, response, primary, slug) {
|
||||
const dc = url.searchParams.get(API_DATACENTER_KEY) || '';
|
||||
return response.map((item, i, arr) => {
|
||||
return {
|
||||
[DATACENTER_KEY]: dc,
|
||||
[PRIMARY_KEY]: this.uidForURL(url, item),
|
||||
[SLUG_KEY]: item,
|
||||
};
|
||||
});
|
||||
},
|
||||
// handleSingleResponse: function(url, response, primary, slug) {
|
||||
// return this._super(url, removeNull(response[0]), PRIMARY_KEY, SLUG_KEY);
|
||||
// },
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
const method = requestData.method;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case response === true:
|
||||
response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
case this.isQueryRecord(url, method):
|
||||
response = this.handleSingleResponse(url, removeNull(response[0]), PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
const data = this._super(...arguments);
|
||||
let value = '';
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
case REQUEST_CREATE:
|
||||
value = data.kv.Value;
|
||||
if (typeof value === 'string') {
|
||||
return get(this, 'decoder').execute(value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
methodForRequest: function(params) {
|
||||
switch (params.requestType) {
|
||||
case REQUEST_DELETE:
|
||||
return HTTP_DELETE;
|
||||
case REQUEST_CREATE:
|
||||
return HTTP_PUT;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
return request`
|
||||
DELETE /v1/kv/${keyToArray(data[SLUG_KEY])}?${{
|
||||
[API_DATACENTER_KEY]: data[DATACENTER_KEY],
|
||||
recurse,
|
||||
}}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,100 +1,37 @@
|
|||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/node';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
// TODO: Looks like ID just isn't used at all
|
||||
// consider just using .Node for the SLUG_KEY
|
||||
const fillSlug = function(item) {
|
||||
if (item[SLUG_KEY] === '') {
|
||||
item[SLUG_KEY] = item['Node'];
|
||||
}
|
||||
return item;
|
||||
};
|
||||
import Adapter from './application';
|
||||
export default Adapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
return this.appendURL('internal/ui/nodes', [], this.cleanQuery(query));
|
||||
requestForQuery: function(request, { dc, index, id }) {
|
||||
return request`
|
||||
GET /v1/internal/ui/nodes?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('internal/ui/node', [query.id], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/internal/ui/node/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForRequest: function({ type, snapshot, requestType }) {
|
||||
switch (requestType) {
|
||||
case 'queryLeader':
|
||||
return this.urlForQueryLeader(snapshot, type.modelName);
|
||||
}
|
||||
return this._super(...arguments);
|
||||
requestForQueryLeader: function(request, { dc }) {
|
||||
return request`
|
||||
GET /v1/status/leader?${{ dc }}
|
||||
`;
|
||||
},
|
||||
urlForQueryLeader: function(query, modelName) {
|
||||
// https://www.consul.io/api/status.html#get-raft-leader
|
||||
return this.appendURL('status/leader', [], this.cleanQuery(query));
|
||||
},
|
||||
isQueryLeader: function(url, method) {
|
||||
return url.pathname === this.parseURL(this.urlForQueryLeader({})).pathname;
|
||||
},
|
||||
queryLeader: function(store, modelClass, id, snapshot) {
|
||||
const params = {
|
||||
store: store,
|
||||
type: modelClass,
|
||||
id: id,
|
||||
snapshot: snapshot,
|
||||
requestType: 'queryLeader',
|
||||
};
|
||||
// _requestFor is private... but these methods aren't, until they disappear..
|
||||
const request = {
|
||||
method: this.methodForRequest(params),
|
||||
url: this.urlForRequest(params),
|
||||
headers: this.headersForRequest(params),
|
||||
data: this.dataForRequest(params),
|
||||
};
|
||||
// TODO: private..
|
||||
return this._makeRequest(request);
|
||||
},
|
||||
handleBatchResponse: function(url, response, primary, slug) {
|
||||
const dc = url.searchParams.get(API_DATACENTER_KEY) || '';
|
||||
return response.map((item, i, arr) => {
|
||||
// this can go in the serializer
|
||||
item = fillSlug(item);
|
||||
// this could be replaced by handleSingleResponse
|
||||
// maybe perf test first although even polyfilled searchParams should be super fast
|
||||
return {
|
||||
...item,
|
||||
...{
|
||||
[DATACENTER_KEY]: dc,
|
||||
[PRIMARY_KEY]: this.uidForURL(url, item[SLUG_KEY]),
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
const method = requestData.method;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
let temp, port, address;
|
||||
switch (true) {
|
||||
case this.isQueryLeader(url, method):
|
||||
// This response is just an ip:port like `"10.0.0.1:8000"`
|
||||
// split it and make it look like a `C`onsul.`R`esponse
|
||||
// popping off the end for ports should cover us for IPv6 addresses
|
||||
// as we should always get a `address:port` or `[a:dd:re:ss]:port` combo
|
||||
temp = response.split(':');
|
||||
port = temp.pop();
|
||||
address = temp.join(':');
|
||||
response = {
|
||||
Address: address,
|
||||
Port: port,
|
||||
};
|
||||
break;
|
||||
case this.isQueryRecord(url, method):
|
||||
response = this.handleSingleResponse(url, fillSlug(response), PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
queryLeader: function(store, type, id, snapshot) {
|
||||
return this.request(
|
||||
function(adapter, request, serialized, unserialized) {
|
||||
return adapter.requestForQueryLeader(request, serialized, unserialized);
|
||||
},
|
||||
function(serializer, respond, serialized, unserialized) {
|
||||
return serializer.respondForQueryLeader(respond, serialized, unserialized);
|
||||
},
|
||||
snapshot,
|
||||
type.modelName
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,73 +1,43 @@
|
|||
import Adapter, {
|
||||
REQUEST_CREATE,
|
||||
REQUEST_UPDATE,
|
||||
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
|
||||
} from './application';
|
||||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/policy';
|
||||
import { SLUG_KEY } from 'consul-ui/models/policy';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
import { PUT as HTTP_PUT } from 'consul-ui/utils/http/method';
|
||||
|
||||
export default Adapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
return this.appendURL('acl/policies', [], this.cleanQuery(query));
|
||||
requestForQuery: function(request, { dc, index, id }) {
|
||||
return request`
|
||||
GET /v1/acl/policies?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('acl/policy', [query.id], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/acl/policy/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForCreateRecord: function(modelName, snapshot) {
|
||||
return this.appendURL('acl/policy', [], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
requestForCreateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/acl/policy?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForUpdateRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('acl/policy', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
requestForUpdateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/acl/policy/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForDeleteRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('acl/policy', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
},
|
||||
urlForTranslateRecord: function(modelName, snapshot) {
|
||||
return this.appendURL('acl/policy/translate', [], {});
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
const data = this._super(...arguments);
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
case REQUEST_CREATE:
|
||||
return data.policy;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case response === true:
|
||||
response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
case Array.isArray(response):
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleSingleResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
},
|
||||
methodForRequest: function(params) {
|
||||
switch (params.requestType) {
|
||||
case REQUEST_CREATE:
|
||||
return HTTP_PUT;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
requestForDeleteRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
DELETE /v1/acl/policy/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
import Adapter from './application';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/proxy';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
export default Adapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQuery: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
// https://www.consul.io/api/catalog.html#list-nodes-for-connect-capable-service
|
||||
return this.appendURL('catalog/connect', [query.id], this.cleanQuery(query));
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
return request`
|
||||
GET /v1/catalog/connect/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,72 +1,43 @@
|
|||
import Adapter, {
|
||||
REQUEST_CREATE,
|
||||
REQUEST_UPDATE,
|
||||
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
|
||||
} from './application';
|
||||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/role';
|
||||
import { SLUG_KEY } from 'consul-ui/models/role';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
import { PUT as HTTP_PUT } from 'consul-ui/utils/http/method';
|
||||
|
||||
import WithPolicies from 'consul-ui/mixins/policy/as-many';
|
||||
export default Adapter.extend({
|
||||
requestForQuery: function(request, { dc, index, id }) {
|
||||
return request`
|
||||
GET /v1/acl/roles?${{ dc }}
|
||||
|
||||
export default Adapter.extend(WithPolicies, {
|
||||
urlForQuery: function(query, modelName) {
|
||||
return this.appendURL('acl/roles', [], this.cleanQuery(query));
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('acl/role', [query.id], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/acl/role/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForCreateRecord: function(modelName, snapshot) {
|
||||
return this.appendURL('acl/role', [], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
requestForCreateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/acl/role?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForUpdateRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('acl/role', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
requestForUpdateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/acl/role/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForDeleteRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('acl/role', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case response === true:
|
||||
response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
case Array.isArray(response):
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleSingleResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
},
|
||||
methodForRequest: function(params) {
|
||||
switch (params.requestType) {
|
||||
case REQUEST_CREATE:
|
||||
return HTTP_PUT;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
const data = this._super(...arguments);
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
case REQUEST_CREATE:
|
||||
return data.role;
|
||||
}
|
||||
return data;
|
||||
requestForDeleteRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
DELETE /v1/acl/role/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,31 +1,20 @@
|
|||
import Adapter from './application';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/service';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
const URL_PREFIX_SINGLE = 'health/service';
|
||||
const URL_PREFIX_MULTIPLE = 'internal/ui/services';
|
||||
export default Adapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
return this.appendURL(URL_PREFIX_MULTIPLE, [], this.cleanQuery(query));
|
||||
requestForQuery: function(request, { dc, index }) {
|
||||
return request`
|
||||
GET /v1/internal/ui/services?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL(URL_PREFIX_SINGLE, [query.id], this.cleanQuery(query));
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
const method = requestData.method;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case this.isQueryRecord(url, method):
|
||||
response = this.handleSingleResponse(url, { Nodes: response }, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
return request`
|
||||
GET /v1/health/service/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,55 +1,31 @@
|
|||
import Adapter, {
|
||||
REQUEST_DELETE,
|
||||
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
|
||||
} from './application';
|
||||
|
||||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/session';
|
||||
import { PUT as HTTP_PUT } from 'consul-ui/utils/http/method';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
import { SLUG_KEY } from 'consul-ui/models/session';
|
||||
|
||||
export default Adapter.extend({
|
||||
urlForQuery: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQuery: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('session/node', [query.id], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/session/node/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('session/info', [query.id], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/session/info/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForDeleteRecord: function(id, modelName, snapshot) {
|
||||
const query = {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
};
|
||||
return this.appendURL('session/destroy', [snapshot.attr(SLUG_KEY)], query);
|
||||
},
|
||||
methodForRequest: function(params) {
|
||||
switch (params.requestType) {
|
||||
case REQUEST_DELETE:
|
||||
return HTTP_PUT;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
const method = requestData.method;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case response === true:
|
||||
response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
case this.isQueryRecord(url, method):
|
||||
response = this.handleSingleResponse(url, response[0], PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
requestForDeleteRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/session/destroy/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
`;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,185 +1,110 @@
|
|||
import Adapter, { DATACENTER_QUERY_PARAM as API_DATACENTER_KEY } from './application';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Adapter, {
|
||||
REQUEST_CREATE,
|
||||
REQUEST_UPDATE,
|
||||
DATACENTER_QUERY_PARAM as API_DATACENTER_KEY,
|
||||
} from './application';
|
||||
|
||||
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/token';
|
||||
import { SLUG_KEY } from 'consul-ui/models/token';
|
||||
import { FOREIGN_KEY as DATACENTER_KEY } from 'consul-ui/models/dc';
|
||||
import { OK as HTTP_OK } from 'consul-ui/utils/http/status';
|
||||
import { PUT as HTTP_PUT } from 'consul-ui/utils/http/method';
|
||||
|
||||
import WithPolicies from 'consul-ui/mixins/policy/as-many';
|
||||
import WithRoles from 'consul-ui/mixins/role/as-many';
|
||||
|
||||
import { get } from '@ember/object';
|
||||
|
||||
const REQUEST_CLONE = 'cloneRecord';
|
||||
const REQUEST_SELF = 'querySelf';
|
||||
|
||||
export default Adapter.extend(WithRoles, WithPolicies, {
|
||||
export default Adapter.extend({
|
||||
store: service('store'),
|
||||
cleanQuery: function(_query) {
|
||||
const query = this._super(...arguments);
|
||||
// TODO: Make sure policy is being passed through
|
||||
delete _query.policy;
|
||||
// take off the secret for /self
|
||||
delete query.secret;
|
||||
return query;
|
||||
|
||||
requestForQuery: function(request, { dc, index, role, policy }) {
|
||||
return request`
|
||||
GET /v1/acl/tokens?${{ role, policy, dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQuery: function(query, modelName) {
|
||||
return this.appendURL('acl/tokens', [], this.cleanQuery(query));
|
||||
},
|
||||
urlForQueryRecord: function(query, modelName) {
|
||||
if (typeof query.id === 'undefined') {
|
||||
requestForQueryRecord: function(request, { dc, index, id }) {
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this.appendURL('acl/token', [query.id], this.cleanQuery(query));
|
||||
return request`
|
||||
GET /v1/acl/token/${id}?${{ dc }}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
urlForQuerySelf: function(query, modelName) {
|
||||
return this.appendURL('acl/token/self', [], this.cleanQuery(query));
|
||||
requestForCreateRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
PUT /v1/acl/token?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
`;
|
||||
},
|
||||
urlForCreateRecord: function(modelName, snapshot) {
|
||||
return this.appendURL('acl/token', [], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
},
|
||||
urlForUpdateRecord: function(id, modelName, snapshot) {
|
||||
requestForUpdateRecord: function(request, serialized, data) {
|
||||
// TODO: here we check data['Rules'] not serialized['Rules']
|
||||
// data.Rules is not undefined, and serialized.Rules is not null
|
||||
// revisit this at some point we should probably use serialized here
|
||||
|
||||
// If a token has Rules, use the old API
|
||||
if (typeof snapshot.attr('Rules') !== 'undefined') {
|
||||
return this.appendURL('acl/update', [], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
if (typeof data['Rules'] !== 'undefined') {
|
||||
// https://www.consul.io/api/acl/legacy.html#update-acl-token
|
||||
return request`
|
||||
PUT /v1/acl/update?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
}
|
||||
return this.appendURL('acl/token', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
return request`
|
||||
PUT /v1/acl/token/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
|
||||
${serialized}
|
||||
`;
|
||||
},
|
||||
urlForDeleteRecord: function(id, modelName, snapshot) {
|
||||
return this.appendURL('acl/token', [snapshot.attr(SLUG_KEY)], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
requestForDeleteRecord: function(request, serialized, data) {
|
||||
return request`
|
||||
DELETE /v1/acl/token/${data[SLUG_KEY]}?${{ [API_DATACENTER_KEY]: data[DATACENTER_KEY] }}
|
||||
`;
|
||||
},
|
||||
urlForRequest: function({ type, snapshot, requestType }) {
|
||||
switch (requestType) {
|
||||
case 'cloneRecord':
|
||||
return this.urlForCloneRecord(type.modelName, snapshot);
|
||||
case 'querySelf':
|
||||
return this.urlForQuerySelf(snapshot, type.modelName);
|
||||
requestForSelf: function(request, serialized, { dc, index, secret }) {
|
||||
// TODO: Change here and elsewhere to use Authorization Bearer Token
|
||||
// https://github.com/hashicorp/consul/pull/4502
|
||||
return request`
|
||||
GET /v1/acl/token/self?${{ dc }}
|
||||
X-Consul-Token: ${secret}
|
||||
|
||||
${{ index }}
|
||||
`;
|
||||
},
|
||||
requestForCloneRecord: function(request, serialized, unserialized) {
|
||||
// this uses snapshots
|
||||
const id = unserialized[SLUG_KEY];
|
||||
const dc = unserialized[DATACENTER_KEY];
|
||||
if (typeof id === 'undefined') {
|
||||
throw new Error('You must specify an id');
|
||||
}
|
||||
return this._super(...arguments);
|
||||
return request`
|
||||
PUT /v1/acl/token/${id}/clone?${{ [API_DATACENTER_KEY]: dc }}
|
||||
`;
|
||||
},
|
||||
urlForCloneRecord: function(modelName, snapshot) {
|
||||
return this.appendURL('acl/token', [snapshot.attr(SLUG_KEY), 'clone'], {
|
||||
[API_DATACENTER_KEY]: snapshot.attr(DATACENTER_KEY),
|
||||
});
|
||||
// TODO: self doesn't get passed a snapshot right now
|
||||
// ideally it would just for consistency
|
||||
// thing is its probably not the same shape as a 'Token',
|
||||
// plus we can't create Snapshots as they are private, see services/store.js
|
||||
self: function(store, type, id, unserialized) {
|
||||
return this.request(
|
||||
function(adapter, request, serialized, unserialized) {
|
||||
return adapter.requestForSelf(request, serialized, unserialized);
|
||||
},
|
||||
function(serializer, respond, serialized, unserialized) {
|
||||
return serializer.respondForQueryRecord(respond, serialized, unserialized);
|
||||
},
|
||||
unserialized,
|
||||
type.modelName
|
||||
);
|
||||
},
|
||||
self: function(store, modelClass, snapshot) {
|
||||
const params = {
|
||||
store: store,
|
||||
type: modelClass,
|
||||
snapshot: snapshot,
|
||||
requestType: 'querySelf',
|
||||
};
|
||||
// _requestFor is private... but these methods aren't, until they disappear..
|
||||
const request = {
|
||||
method: this.methodForRequest(params),
|
||||
url: this.urlForRequest(params),
|
||||
headers: this.headersForRequest(params),
|
||||
data: this.dataForRequest(params),
|
||||
};
|
||||
// TODO: private..
|
||||
return this._makeRequest(request);
|
||||
},
|
||||
clone: function(store, modelClass, id, snapshot) {
|
||||
const params = {
|
||||
store: store,
|
||||
type: modelClass,
|
||||
id: id,
|
||||
snapshot: snapshot,
|
||||
requestType: 'cloneRecord',
|
||||
};
|
||||
// _requestFor is private... but these methods aren't, until they disappear..
|
||||
const request = {
|
||||
method: this.methodForRequest(params),
|
||||
url: this.urlForRequest(params),
|
||||
headers: this.headersForRequest(params),
|
||||
data: this.dataForRequest(params),
|
||||
};
|
||||
// TODO: private..
|
||||
return this._makeRequest(request);
|
||||
},
|
||||
handleSingleResponse: function(url, response, primary, slug) {
|
||||
// Convert an old style update response to a new style
|
||||
if (typeof response['ID'] !== 'undefined') {
|
||||
const item = get(this, 'store')
|
||||
.peekAll('token')
|
||||
.findBy('SecretID', response['ID']);
|
||||
if (item) {
|
||||
response['SecretID'] = response['ID'];
|
||||
response['AccessorID'] = get(item, 'AccessorID');
|
||||
}
|
||||
}
|
||||
return this._super(url, response, primary, slug);
|
||||
},
|
||||
handleResponse: function(status, headers, payload, requestData) {
|
||||
let response = payload;
|
||||
if (status === HTTP_OK) {
|
||||
const url = this.parseURL(requestData.url);
|
||||
switch (true) {
|
||||
case response === true:
|
||||
response = this.handleBooleanResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
case Array.isArray(response):
|
||||
response = this.handleBatchResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
break;
|
||||
default:
|
||||
response = this.handleSingleResponse(url, response, PRIMARY_KEY, SLUG_KEY);
|
||||
}
|
||||
}
|
||||
return this._super(status, headers, response, requestData);
|
||||
},
|
||||
methodForRequest: function(params) {
|
||||
switch (params.requestType) {
|
||||
case REQUEST_CLONE:
|
||||
case REQUEST_CREATE:
|
||||
return HTTP_PUT;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
headersForRequest: function(params) {
|
||||
switch (params.requestType) {
|
||||
case REQUEST_SELF:
|
||||
return {
|
||||
'X-Consul-Token': params.snapshot.secret,
|
||||
};
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
let data = this._super(...arguments);
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
// If a token has Rules, use the old API
|
||||
if (typeof data.token['Rules'] !== 'undefined') {
|
||||
data.token['ID'] = data.token['SecretID'];
|
||||
data.token['Name'] = data.token['Description'];
|
||||
}
|
||||
// falls through
|
||||
case REQUEST_CREATE:
|
||||
data = data.token;
|
||||
break;
|
||||
case REQUEST_SELF:
|
||||
return {};
|
||||
case REQUEST_CLONE:
|
||||
data = {};
|
||||
break;
|
||||
}
|
||||
// make sure we never send the SecretID
|
||||
if (data && typeof data['SecretID'] !== 'undefined') {
|
||||
delete data['SecretID'];
|
||||
}
|
||||
return data;
|
||||
clone: function(store, type, id, snapshot) {
|
||||
return this.request(
|
||||
function(adapter, request, serialized, unserialized) {
|
||||
return adapter.requestForCloneRecord(request, serialized, unserialized);
|
||||
},
|
||||
function(serializer, respond, serialized, unserialized) {
|
||||
// here we just have to pass through the dc (like when querying)
|
||||
// eventually the id is created with this dc value and the id talen from the
|
||||
// json response of `acls/token/*/clone`
|
||||
return serializer.respondForQueryRecord(respond, {
|
||||
[API_DATACENTER_KEY]: unserialized[SLUG_KEY],
|
||||
});
|
||||
},
|
||||
snapshot,
|
||||
type.modelName
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
import SlotsMixin from 'block-slots';
|
||||
import { get } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import templatize from 'consul-ui/utils/templatize';
|
||||
export default Component.extend(SlotsMixin, {
|
||||
|
@ -13,9 +12,9 @@ export default Component.extend(SlotsMixin, {
|
|||
didReceiveAttrs: function() {
|
||||
this._super(...arguments);
|
||||
// right now only manually added classes are hoisted to <html>
|
||||
const $root = get(this, 'dom').root();
|
||||
let cls = get(this, 'class') || '';
|
||||
if (get(this, 'loading')) {
|
||||
const $root = this.dom.root();
|
||||
let cls = this['class'] || '';
|
||||
if (this.loading) {
|
||||
cls += ' loading';
|
||||
} else {
|
||||
$root.classList.remove(...templatize(['loading']));
|
||||
|
@ -39,9 +38,9 @@ export default Component.extend(SlotsMixin, {
|
|||
},
|
||||
didDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
const cls = get(this, 'class') + ' loading';
|
||||
const cls = this['class'] + ' loading';
|
||||
if (cls) {
|
||||
const $root = get(this, 'dom').root();
|
||||
const $root = this.dom.root();
|
||||
$root.classList.remove(...templatize(cls.split(' ')));
|
||||
}
|
||||
},
|
||||
|
|
|
@ -8,7 +8,7 @@ export default Component.extend(WithListeners, SlotsMixin, {
|
|||
didReceiveAttrs: function() {
|
||||
this._super(...arguments);
|
||||
this.removeListeners();
|
||||
const dispatcher = get(this, 'dispatcher');
|
||||
const dispatcher = this.dispatcher;
|
||||
if (dispatcher) {
|
||||
this.listen(dispatcher, 'change', e => {
|
||||
set(this, 'items', e.target.data);
|
||||
|
|
|
@ -23,15 +23,15 @@ export default Component.extend(SlotsMixin, WithListeners, {
|
|||
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.searchable = get(this, 'container').searchable(get(this, 'type'));
|
||||
this.form = get(this, 'formContainer').form(get(this, 'type'));
|
||||
this.form.clear({ Datacenter: get(this, 'dc') });
|
||||
this.searchable = this.container.searchable(this.type);
|
||||
this.form = this.formContainer.form(this.type);
|
||||
this.form.clear({ Datacenter: this.dc });
|
||||
},
|
||||
options: computed('selectedOptions.[]', 'allOptions.[]', function() {
|
||||
// It's not massively important here that we are defaulting `items` and
|
||||
// losing reference as its just to figure out the diff
|
||||
let options = get(this, 'allOptions') || [];
|
||||
const items = get(this, 'selectedOptions') || [];
|
||||
let options = this.allOptions || [];
|
||||
const items = this.selectedOptions || [];
|
||||
if (get(items, 'length') > 0) {
|
||||
// find a proper ember-data diff
|
||||
options = options.filter(item => !items.findBy('ID', get(item, 'ID')));
|
||||
|
@ -52,17 +52,17 @@ export default Component.extend(SlotsMixin, WithListeners, {
|
|||
});
|
||||
},
|
||||
reset: function() {
|
||||
get(this, 'form').clear({ Datacenter: get(this, 'dc') });
|
||||
this.form.clear({ Datacenter: this.dc });
|
||||
},
|
||||
open: function() {
|
||||
if (!get(this, 'allOptions.closed')) {
|
||||
set(this, 'allOptions', get(this, 'repo').findAllByDatacenter(get(this, 'dc')));
|
||||
set(this, 'allOptions', this.repo.findAllByDatacenter(this.dc));
|
||||
}
|
||||
},
|
||||
save: function(item, items, success = function() {}) {
|
||||
// Specifically this saves an 'new' option/child
|
||||
// and then adds it to the selectedOptions, not options
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
set(item, 'CreateTime', new Date().getTime());
|
||||
// TODO: temporary async
|
||||
// this should be `set(this, 'item', repo.persist(item));`
|
||||
|
@ -85,7 +85,7 @@ export default Component.extend(SlotsMixin, WithListeners, {
|
|||
this.listen(item, 'error', this.error.bind(this));
|
||||
},
|
||||
remove: function(item, items) {
|
||||
const prop = get(this, 'repo').getSlugKey();
|
||||
const prop = this.repo.getSlugKey();
|
||||
const value = get(item, prop);
|
||||
const pos = items.findIndex(function(item) {
|
||||
return get(item, prop) === value;
|
||||
|
@ -96,7 +96,7 @@ export default Component.extend(SlotsMixin, WithListeners, {
|
|||
this.onchange({ target: this });
|
||||
},
|
||||
change: function(e, value, item) {
|
||||
const event = get(this, 'dom').normalizeEvent(...arguments);
|
||||
const event = this.dom.normalizeEvent(...arguments);
|
||||
const items = value;
|
||||
switch (event.target.name) {
|
||||
case 'items[]':
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
const DEFAULTS = {
|
||||
tabSize: 2,
|
||||
|
@ -21,24 +21,24 @@ export default Component.extend({
|
|||
oninput: function() {},
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
set(this, 'modes', get(this, 'helper').modes());
|
||||
set(this, 'modes', this.helper.modes());
|
||||
},
|
||||
didReceiveAttrs: function() {
|
||||
this._super(...arguments);
|
||||
const editor = get(this, 'editor');
|
||||
const editor = this.editor;
|
||||
if (editor) {
|
||||
editor.setOption('readOnly', get(this, 'readonly'));
|
||||
editor.setOption('readOnly', this.readonly);
|
||||
}
|
||||
},
|
||||
setMode: function(mode) {
|
||||
set(this, 'options', {
|
||||
...DEFAULTS,
|
||||
mode: mode.mime,
|
||||
readOnly: get(this, 'readonly'),
|
||||
readOnly: this.readonly,
|
||||
});
|
||||
const editor = get(this, 'editor');
|
||||
const editor = this.editor;
|
||||
editor.setOption('mode', mode.mime);
|
||||
get(this, 'helper').lint(editor, mode.mode);
|
||||
this.helper.lint(editor, mode.mode);
|
||||
set(this, 'mode', mode);
|
||||
},
|
||||
willDestroyElement: function() {
|
||||
|
@ -49,7 +49,7 @@ export default Component.extend({
|
|||
},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
const $code = get(this, 'dom').element('textarea ~ pre code', get(this, 'element'));
|
||||
const $code = this.dom.element('textarea ~ pre code', this.element);
|
||||
if ($code.firstChild) {
|
||||
this.observer = new MutationObserver(([e]) => {
|
||||
this.oninput(set(this, 'value', e.target.wholeText));
|
||||
|
@ -62,27 +62,25 @@ export default Component.extend({
|
|||
});
|
||||
set(this, 'value', $code.firstChild.wholeText);
|
||||
}
|
||||
set(this, 'editor', get(this, 'helper').getEditor(this.element));
|
||||
get(this, 'settings')
|
||||
.findBySlug('code-editor')
|
||||
.then(mode => {
|
||||
const modes = get(this, 'modes');
|
||||
const syntax = get(this, 'syntax');
|
||||
if (syntax) {
|
||||
mode = modes.find(function(item) {
|
||||
return item.name.toLowerCase() == syntax.toLowerCase();
|
||||
});
|
||||
}
|
||||
mode = !mode ? modes[0] : mode;
|
||||
this.setMode(mode);
|
||||
});
|
||||
set(this, 'editor', this.helper.getEditor(this.element));
|
||||
this.settings.findBySlug('code-editor').then(mode => {
|
||||
const modes = this.modes;
|
||||
const syntax = this.syntax;
|
||||
if (syntax) {
|
||||
mode = modes.find(function(item) {
|
||||
return item.name.toLowerCase() == syntax.toLowerCase();
|
||||
});
|
||||
}
|
||||
mode = !mode ? modes[0] : mode;
|
||||
this.setMode(mode);
|
||||
});
|
||||
},
|
||||
didAppear: function() {
|
||||
get(this, 'editor').refresh();
|
||||
this.editor.refresh();
|
||||
},
|
||||
actions: {
|
||||
change: function(value) {
|
||||
get(this, 'settings').persist({
|
||||
this.settings.persist({
|
||||
'code-editor': value,
|
||||
});
|
||||
this.setMode(value);
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
import Component from '@ember/component';
|
||||
|
||||
import SlotsMixin from 'block-slots';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
const cancel = function() {
|
||||
set(this, 'confirming', false);
|
||||
};
|
||||
const execute = function() {
|
||||
this.sendAction(...['actionName', ...get(this, 'arguments')]);
|
||||
this.sendAction(...['actionName', ...this['arguments']]);
|
||||
};
|
||||
const confirm = function() {
|
||||
const [action, ...args] = arguments;
|
||||
|
@ -18,21 +18,21 @@ const confirm = function() {
|
|||
if (this._isRegistered('dialog')) {
|
||||
set(this, 'confirming', true);
|
||||
} else {
|
||||
get(this, 'confirm')
|
||||
.execute(get(this, 'message'))
|
||||
this._confirm
|
||||
.execute(this.message)
|
||||
.then(confirmed => {
|
||||
if (confirmed) {
|
||||
this.execute();
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
return get(this, 'error').execute(...arguments);
|
||||
return this.error.execute(...arguments);
|
||||
});
|
||||
}
|
||||
};
|
||||
export default Component.extend(SlotsMixin, {
|
||||
classNameBindings: ['confirming'],
|
||||
confirm: service('confirm'),
|
||||
_confirm: service('confirm'),
|
||||
error: service('error'),
|
||||
classNames: ['with-confirmation'],
|
||||
message: 'Are you sure?',
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import Component from '@ember/component';
|
||||
import { get } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
import WithListeners from 'consul-ui/mixins/with-listeners';
|
||||
|
@ -25,7 +24,7 @@ export default Component.extend(WithListeners, {
|
|||
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
const clipboard = get(this, 'clipboard').execute(
|
||||
const clipboard = this.clipboard.execute(
|
||||
this.delegateClickEvent ? `#${this.elementId}` : this.element
|
||||
);
|
||||
['success', 'error'].map(event => {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
import Component from '@ember/component';
|
||||
const append = function(content) {
|
||||
this.element.appendChild(content);
|
||||
|
@ -12,10 +11,10 @@ export default Component.extend({
|
|||
},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
get(this, 'buffer').on('add', this.append);
|
||||
this.buffer.on('add', this.append);
|
||||
},
|
||||
didDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
get(this, 'buffer').off('add', this.append);
|
||||
this.buffer.off('add', this.append);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
import Component from '@ember/component';
|
||||
export default Component.extend({
|
||||
buffer: service('dom-buffer'),
|
||||
|
@ -10,10 +9,10 @@ export default Component.extend({
|
|||
},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
get(this, 'buffer').add(this.getBufferName(), this.element);
|
||||
this.buffer.add(this.getBufferName(), this.element);
|
||||
},
|
||||
didDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
get(this, 'buffer').remove(this.getBufferName());
|
||||
this.buffer.remove(this.getBufferName());
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { Promise } from 'rsvp';
|
||||
|
||||
|
@ -21,8 +21,8 @@ export default Component.extend(SlotsMixin, {
|
|||
this.error = this._error.bind(this);
|
||||
},
|
||||
applyTransition: function() {
|
||||
const wait = get(this, 'wait').execute;
|
||||
const className = get(this, 'transitionClassName');
|
||||
const wait = this.wait.execute;
|
||||
const className = this.transitionClassName;
|
||||
// TODO: Make 0 default in wait
|
||||
wait(0)
|
||||
.then(() => {
|
||||
|
@ -31,7 +31,7 @@ export default Component.extend(SlotsMixin, {
|
|||
})
|
||||
.then(() => {
|
||||
return new Promise(resolve => {
|
||||
get(this, 'dom')
|
||||
this.dom
|
||||
.element(`.${className}`, this.element)
|
||||
.addEventListener('transitionend', resolve);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Component from '@ember/component';
|
||||
import SlotsMixin from 'block-slots';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import WithListeners from 'consul-ui/mixins/with-listeners';
|
||||
// match anything that isn't a [ or ] into multiple groups
|
||||
|
@ -22,7 +21,7 @@ export default Component.extend(WithListeners, SlotsMixin, {
|
|||
|
||||
actions: {
|
||||
change: function(e, value, item) {
|
||||
let event = get(this, 'dom').normalizeEvent(e, value);
|
||||
let event = this.dom.normalizeEvent(e, value);
|
||||
// currently form-components don't deal with deeply nested forms, only top level
|
||||
// we therefore grab the end of the nest off here,
|
||||
// so role[policy][Rules] will end up as policy[Rules]
|
||||
|
@ -34,11 +33,11 @@ export default Component.extend(WithListeners, SlotsMixin, {
|
|||
const prop = matches[matches.length - 1][0];
|
||||
let name;
|
||||
if (prop.indexOf('[') === -1) {
|
||||
name = `${get(this, 'type')}[${prop}]`;
|
||||
name = `${this.type}[${prop}]`;
|
||||
} else {
|
||||
name = prop;
|
||||
}
|
||||
const form = get(this, 'form');
|
||||
const form = this.form;
|
||||
try {
|
||||
form.handleEvent(event, name);
|
||||
this.onchange({ target: this });
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import Component from '@ember/component';
|
||||
import { get } from '@ember/object';
|
||||
export default Component.extend({
|
||||
tagName: 'fieldset',
|
||||
classNames: ['freetext-filter'],
|
||||
onchange: function(e) {
|
||||
let searchable = get(this, 'searchable');
|
||||
let searchable = this.searchable;
|
||||
if (!Array.isArray(searchable)) {
|
||||
searchable = [searchable];
|
||||
}
|
||||
|
|
|
@ -5,18 +5,16 @@ export default Component.extend({
|
|||
dom: service('dom'),
|
||||
isDropdownVisible: false,
|
||||
didInsertElement: function() {
|
||||
get(this, 'dom')
|
||||
.root()
|
||||
.classList.remove('template-with-vertical-menu');
|
||||
this.dom.root().classList.remove('template-with-vertical-menu');
|
||||
},
|
||||
actions: {
|
||||
dropdown: function(e) {
|
||||
if (get(this, 'dcs.length') > 0) {
|
||||
set(this, 'isDropdownVisible', !get(this, 'isDropdownVisible'));
|
||||
set(this, 'isDropdownVisible', !this.isDropdownVisible);
|
||||
}
|
||||
},
|
||||
change: function(e) {
|
||||
const dom = get(this, 'dom');
|
||||
const dom = this.dom;
|
||||
const win = dom.viewport();
|
||||
const $root = dom.root();
|
||||
const $body = dom.element('body');
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import Component from '@ember/component';
|
||||
import { get, computed } from '@ember/object';
|
||||
import { computed } from '@ember/object';
|
||||
export default Component.extend({
|
||||
tagName: '',
|
||||
count: computed('value', function() {
|
||||
const value = get(this, 'value');
|
||||
const value = this.value;
|
||||
if (Array.isArray(value)) {
|
||||
return value.length;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { filter } from '@ember/object/computed';
|
||||
import Component from '@ember/component';
|
||||
import { computed, get } from '@ember/object';
|
||||
import style from 'ember-computed-style';
|
||||
|
@ -5,11 +6,11 @@ export default Component.extend({
|
|||
classNames: ['healthchecked-resource'],
|
||||
attributeBindings: ['style'],
|
||||
style: style('gridRowEnd'),
|
||||
unhealthy: computed.filter(`checks.@each.Status`, function(item) {
|
||||
unhealthy: filter(`checks.@each.Status`, function(item) {
|
||||
const status = get(item, 'Status');
|
||||
return status === 'critical' || status === 'warning';
|
||||
}),
|
||||
healthy: computed.filter(`checks.@each.Status`, function(item) {
|
||||
healthy: filter(`checks.@each.Status`, function(item) {
|
||||
const status = get(item, 'Status');
|
||||
return status === 'passing';
|
||||
}),
|
||||
|
|
|
@ -16,9 +16,9 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
|
|||
onopen: function() {},
|
||||
_open: function(e) {
|
||||
set(this, 'checked', true);
|
||||
if (get(this, 'height') === null) {
|
||||
if (this.height === null) {
|
||||
if (this.element) {
|
||||
const dialogPanel = get(this, 'dom').element('[role="dialog"] > div > div', this.element);
|
||||
const dialogPanel = this.dom.element('[role="dialog"] > div > div', this.element);
|
||||
const rect = dialogPanel.getBoundingClientRect();
|
||||
set(this, 'dialog', dialogPanel);
|
||||
set(this, 'height', rect.height);
|
||||
|
@ -29,25 +29,21 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
|
|||
},
|
||||
didAppear: function() {
|
||||
this._super(...arguments);
|
||||
if (get(this, 'checked')) {
|
||||
get(this, 'dom')
|
||||
.root()
|
||||
.classList.add(...templatize(['with-modal']));
|
||||
if (this.checked) {
|
||||
this.dom.root().classList.add(...templatize(['with-modal']));
|
||||
}
|
||||
},
|
||||
_close: function(e) {
|
||||
set(this, 'checked', false);
|
||||
const dialogPanel = get(this, 'dialog');
|
||||
const dialogPanel = this.dialog;
|
||||
if (dialogPanel) {
|
||||
const overflowing = get(this, 'overflowingClass');
|
||||
const overflowing = this.overflowingClass;
|
||||
if (dialogPanel.classList.contains(overflowing)) {
|
||||
dialogPanel.classList.remove(overflowing);
|
||||
}
|
||||
}
|
||||
// TODO: should we make a didDisappear?
|
||||
get(this, 'dom')
|
||||
.root()
|
||||
.classList.remove(...templatize(['with-modal']));
|
||||
this.dom.root().classList.remove(...templatize(['with-modal']));
|
||||
this.onclose(e);
|
||||
},
|
||||
didReceiveAttrs: function() {
|
||||
|
@ -59,11 +55,11 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
|
|||
// It's not our usecase just yet, but this should check the state
|
||||
// of the thing its linked to, incase that has a `checked` of true
|
||||
// right now we know ours is always false.
|
||||
if (get(this, 'name')) {
|
||||
if (this.name) {
|
||||
set(this, 'checked', false);
|
||||
}
|
||||
if (this.element) {
|
||||
if (get(this, 'checked')) {
|
||||
if (this.checked) {
|
||||
// TODO: probably need an event here
|
||||
// possibly this.element for the target
|
||||
// or find the input
|
||||
|
@ -73,7 +69,7 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
|
|||
},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
if (get(this, 'checked')) {
|
||||
if (this.checked) {
|
||||
// TODO: probably need an event here
|
||||
// possibly this.element for the target
|
||||
// or find the input
|
||||
|
@ -82,16 +78,14 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
|
|||
},
|
||||
didDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
get(this, 'dom')
|
||||
.root()
|
||||
.classList.remove(...templatize(['with-modal']));
|
||||
this.dom.root().classList.remove(...templatize(['with-modal']));
|
||||
},
|
||||
resize: function(e) {
|
||||
if (get(this, 'checked')) {
|
||||
const height = get(this, 'height');
|
||||
if (this.checked) {
|
||||
const height = this.height;
|
||||
if (height !== null) {
|
||||
const dialogPanel = get(this, 'dialog');
|
||||
const overflowing = get(this, 'overflowingClass');
|
||||
const dialogPanel = this.dialog;
|
||||
const overflowing = this.overflowingClass;
|
||||
if (height > e.detail.height) {
|
||||
if (!dialogPanel.classList.contains(overflowing)) {
|
||||
dialogPanel.classList.add(overflowing);
|
||||
|
@ -114,9 +108,9 @@ export default DomBufferComponent.extend(SlotsMixin, WithResizing, {
|
|||
}
|
||||
},
|
||||
close: function() {
|
||||
const $close = get(this, 'dom').element('#modal_close');
|
||||
const $close = this.dom.element('#modal_close');
|
||||
$close.checked = true;
|
||||
const $input = get(this, 'dom').element('input[name="modal"]', this.element);
|
||||
const $input = this.dom.element('input[name="modal"]', this.element);
|
||||
$input.onchange({ target: $input });
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import DomBufferFlushComponent from 'consul-ui/components/dom-buffer-flush';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
export default DomBufferFlushComponent.extend({
|
||||
dom: service('dom'),
|
||||
actions: {
|
||||
change: function(e) {
|
||||
[...get(this, 'dom').elements('[name="modal"]')]
|
||||
[...this.dom.elements('[name="modal"]')]
|
||||
.filter(function(item) {
|
||||
return item.getAttribute('id') !== 'modal_close';
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default Component.extend({
|
||||
|
@ -9,18 +9,18 @@ export default Component.extend({
|
|||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
// TODO: use {{ref}}
|
||||
this.input = get(this, 'dom').element('input', this.element);
|
||||
this.input = this.dom.element('input', this.element);
|
||||
},
|
||||
onchange: function(e) {},
|
||||
search: function(e) {
|
||||
// TODO: Temporarily continue supporting `searchable`
|
||||
let searchable = get(this, 'searchable');
|
||||
let searchable = this.searchable;
|
||||
if (searchable) {
|
||||
if (!Array.isArray(searchable)) {
|
||||
searchable = [searchable];
|
||||
}
|
||||
searchable.forEach(item => {
|
||||
item.search(get(this, 'value'));
|
||||
item.search(this.value);
|
||||
});
|
||||
}
|
||||
this.onchange(e);
|
||||
|
@ -31,8 +31,8 @@ export default Component.extend({
|
|||
keydown: function(e) {
|
||||
switch (e.keyCode) {
|
||||
case 8: // backspace
|
||||
if (e.target.value == '' && get(this, 'value').length > 0) {
|
||||
this.actions.remove.bind(this)(get(this, 'value').length - 1);
|
||||
if (e.target.value == '' && this.value.length > 0) {
|
||||
this.actions.remove.bind(this)(this.value.length - 1);
|
||||
}
|
||||
break;
|
||||
case 27: // escape
|
||||
|
@ -47,15 +47,15 @@ export default Component.extend({
|
|||
this.oninput({ target: this });
|
||||
},
|
||||
remove: function(index, e) {
|
||||
get(this, 'value').removeAt(index, 1);
|
||||
this.value.removeAt(index, 1);
|
||||
this.search({ target: this });
|
||||
this.input.focus();
|
||||
},
|
||||
add: function(e) {
|
||||
const item = get(this, 'item').trim();
|
||||
const item = this.item.trim();
|
||||
if (item !== '') {
|
||||
set(this, 'item', '');
|
||||
const currentItems = get(this, 'value') || [];
|
||||
const currentItems = this.value || [];
|
||||
const items = new Set(currentItems).add(item);
|
||||
if (items.size > currentItems.length) {
|
||||
set(this, 'value', [...items]);
|
||||
|
|
|
@ -13,7 +13,7 @@ export default FormComponent.extend({
|
|||
init: function() {
|
||||
this._super(...arguments);
|
||||
set(this, 'isScoped', get(this, 'item.Datacenters.length') > 0);
|
||||
set(this, 'datacenters', get(this, 'datacenterRepo').findAll());
|
||||
set(this, 'datacenters', this.datacenterRepo.findAll());
|
||||
this.templates = [
|
||||
{
|
||||
name: 'Policy',
|
||||
|
@ -30,7 +30,7 @@ export default FormComponent.extend({
|
|||
try {
|
||||
this._super(...arguments);
|
||||
} catch (err) {
|
||||
const scoped = get(this, 'isScoped');
|
||||
const scoped = this.isScoped;
|
||||
const name = err.target.name;
|
||||
switch (name) {
|
||||
case 'policy[isScoped]':
|
||||
|
@ -38,7 +38,7 @@ export default FormComponent.extend({
|
|||
set(this, 'previousDatacenters', get(this.item, 'Datacenters'));
|
||||
set(this.item, 'Datacenters', null);
|
||||
} else {
|
||||
set(this.item, 'Datacenters', get(this, 'previousDatacenters'));
|
||||
set(this.item, 'Datacenters', this.previousDatacenters);
|
||||
set(this, 'previousDatacenters', null);
|
||||
}
|
||||
set(this, 'isScoped', !scoped);
|
||||
|
@ -46,7 +46,7 @@ export default FormComponent.extend({
|
|||
default:
|
||||
this.onerror(err);
|
||||
}
|
||||
this.onchange({ target: get(this, 'form') });
|
||||
this.onchange({ target: this.form });
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ export default ChildSelectorComponent.extend({
|
|||
classNames: ['policy-selector'],
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
const source = get(this, 'source');
|
||||
const source = this.source;
|
||||
if (source) {
|
||||
const event = 'save';
|
||||
this.listen(source, event, e => {
|
||||
|
@ -26,16 +26,14 @@ export default ChildSelectorComponent.extend({
|
|||
reset: function(e) {
|
||||
this._super(...arguments);
|
||||
set(this, 'isScoped', false);
|
||||
set(this, 'datacenters', get(this, 'datacenterRepo').findAll());
|
||||
set(this, 'datacenters', this.datacenterRepo.findAll());
|
||||
},
|
||||
refreshCodeEditor: function(e, target) {
|
||||
const selector = '.code-editor';
|
||||
get(this, 'dom')
|
||||
.component(selector, target)
|
||||
.didAppear();
|
||||
this.dom.component(selector, target).didAppear();
|
||||
},
|
||||
error: function(e) {
|
||||
const item = get(this, 'item');
|
||||
const item = this.item;
|
||||
const err = e.error;
|
||||
if (typeof err.errors !== 'undefined') {
|
||||
const error = err.errors[0];
|
||||
|
@ -75,9 +73,9 @@ export default ChildSelectorComponent.extend({
|
|||
}
|
||||
// potentially the item could change between load, so we don't check
|
||||
// anything to see if its already loaded here
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
// TODO: Temporarily add dc here, will soon be serialized onto the policy itself
|
||||
const dc = get(this, 'dc');
|
||||
const dc = this.dc;
|
||||
const slugKey = repo.getSlugKey();
|
||||
const slug = get(value, slugKey);
|
||||
updateArrayObject(items, repo.findBySlug(slug, dc), slugKey, slug);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import ChildSelectorComponent from './child-selector';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
|
||||
import { CallableEventSource as EventSource } from 'consul-ui/utils/dom/event-source';
|
||||
|
@ -17,27 +17,25 @@ export default ChildSelectorComponent.extend({
|
|||
policy: alias('policyForm.data'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.policyForm = get(this, 'formContainer').form('policy');
|
||||
this.policyForm = this.formContainer.form('policy');
|
||||
this.source = new EventSource();
|
||||
},
|
||||
actions: {
|
||||
reset: function(e) {
|
||||
this._super(...arguments);
|
||||
get(this, 'policyForm').clear({ Datacenter: get(this, 'dc') });
|
||||
this.policyForm.clear({ Datacenter: this.dc });
|
||||
},
|
||||
dispatch: function(type, data) {
|
||||
this.source.dispatchEvent({ type: type, data: data });
|
||||
},
|
||||
change: function() {
|
||||
const event = get(this, 'dom').normalizeEvent(...arguments);
|
||||
const event = this.dom.normalizeEvent(...arguments);
|
||||
const target = event.target;
|
||||
switch (target.name) {
|
||||
case 'role[state]':
|
||||
set(this, 'state', target.value);
|
||||
if (target.value === 'policy') {
|
||||
get(this, 'dom')
|
||||
.component('.code-editor', target.nextElementSibling)
|
||||
.didAppear();
|
||||
this.dom.component('.code-editor', target.nextElementSibling).didAppear();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import Component from '@ember/component';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
export default Component.extend({
|
||||
classNames: ['sort-control'],
|
||||
direction: 'asc',
|
||||
|
@ -9,7 +9,7 @@ export default Component.extend({
|
|||
if (e.target.type === 'checkbox') {
|
||||
set(this, 'direction', e.target.checked ? 'desc' : 'asc');
|
||||
}
|
||||
this.onchange({ target: { value: `${get(this, 'value')}:${get(this, 'direction')}` } });
|
||||
this.onchange({ target: { value: `${this.value}:${this.direction}` } });
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ import { computed } from '@ember/object';
|
|||
export default Component.extend({
|
||||
classNames: ['tab-section'],
|
||||
'data-test-radiobutton': computed('name,id', function() {
|
||||
return `${this.get('name')}_${this.get('id')}`;
|
||||
return `${this.name}_${this.id}`;
|
||||
}),
|
||||
name: 'tab',
|
||||
onchange: function() {},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import Component from '@ember/component';
|
||||
import SlotsMixin from 'block-slots';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
import { subscribe } from 'consul-ui/utils/computed/purify';
|
||||
|
||||
let uid = 0;
|
||||
|
@ -17,7 +17,7 @@ export default Component.extend(SlotsMixin, {
|
|||
}),
|
||||
actions: {
|
||||
click: function(e) {
|
||||
get(this, 'dom').clickFirstAnchor(e);
|
||||
this.dom.clickFirstAnchor(e);
|
||||
},
|
||||
change: function(item, items, e) {
|
||||
this.onchange(e, item, items);
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/*eslint ember/require-return-from-computed: "warn"*/
|
||||
// TODO: Remove ^
|
||||
|
||||
import Component from '@ember/component';
|
||||
import { get, set, computed } from '@ember/object';
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ export default Component.extend({
|
|||
distances: computed('tomography', function() {
|
||||
const tomography = get(this, 'tomography');
|
||||
let distances = get(tomography, 'distances') || [];
|
||||
// TODO: This should probably be moved into the milliseconds computedProperty
|
||||
/*eslint ember/no-side-effects: "warn"*/
|
||||
distances.forEach((d, i) => {
|
||||
if (d.distance > get(this, 'max')) {
|
||||
set(this, 'max', d.distance);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import ComputedProperty from '@ember/object/computed';
|
||||
import computedFactory from 'consul-ui/utils/computed/factory';
|
||||
import { computed as computedPropertyFactory } from '@ember/object';
|
||||
|
||||
export default class Catchable extends ComputedProperty {
|
||||
catch(cb) {
|
||||
export const computed = function() {
|
||||
const prop = computedPropertyFactory(...arguments);
|
||||
prop.catch = function(cb) {
|
||||
return this.meta({
|
||||
catch: cb,
|
||||
});
|
||||
}
|
||||
}
|
||||
export const computed = computedFactory(Catchable);
|
||||
};
|
||||
return prop;
|
||||
};
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
export default Controller.extend({
|
||||
builder: service('form'),
|
||||
dom: service('dom'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.form = get(this, 'builder').form('acl');
|
||||
this.form = this.builder.form('acl');
|
||||
},
|
||||
setProperties: function(model) {
|
||||
// essentially this replaces the data with changesets
|
||||
|
@ -24,8 +23,8 @@ export default Controller.extend({
|
|||
},
|
||||
actions: {
|
||||
change: function(e, value, item) {
|
||||
const event = get(this, 'dom').normalizeEvent(e, value);
|
||||
get(this, 'form').handleEvent(event);
|
||||
const event = this.dom.normalizeEvent(e, value);
|
||||
this.form.handleEvent(event);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
export default Controller.extend({
|
||||
builder: service('form'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.form = get(this, 'builder').form('policy');
|
||||
this.form = this.builder.form('policy');
|
||||
},
|
||||
setProperties: function(model) {
|
||||
// essentially this replaces the data with changesets
|
||||
|
|
|
@ -16,7 +16,7 @@ export default Controller.extend(WithSearching, {
|
|||
},
|
||||
searchable: computed('items', function() {
|
||||
return get(this, 'searchables.policy')
|
||||
.add(get(this, 'items'))
|
||||
.add(this.items)
|
||||
.search(get(this, this.searchParams.policy));
|
||||
}),
|
||||
actions: {},
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
export default Controller.extend({
|
||||
builder: service('form'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.form = get(this, 'builder').form('role');
|
||||
this.form = this.builder.form('role');
|
||||
},
|
||||
setProperties: function(model) {
|
||||
// essentially this replaces the data with changesets
|
||||
|
|
|
@ -16,7 +16,7 @@ export default Controller.extend(WithSearching, {
|
|||
},
|
||||
searchable: computed('items', function() {
|
||||
return get(this, 'searchables.role')
|
||||
.add(get(this, 'items'))
|
||||
.add(this.items)
|
||||
.search(get(this, this.searchParams.role));
|
||||
}),
|
||||
actions: {},
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import Controller from '@ember/controller';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
export default Controller.extend({
|
||||
dom: service('dom'),
|
||||
builder: service('form'),
|
||||
isScoped: false,
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.form = get(this, 'builder').form('token');
|
||||
this.form = this.builder.form('token');
|
||||
},
|
||||
setProperties: function(model) {
|
||||
// essentially this replaces the data with changesets
|
||||
|
@ -24,8 +23,8 @@ export default Controller.extend({
|
|||
},
|
||||
actions: {
|
||||
change: function(e, value, item) {
|
||||
const event = get(this, 'dom').normalizeEvent(e, value);
|
||||
const form = get(this, 'form');
|
||||
const event = this.dom.normalizeEvent(e, value);
|
||||
const form = this.form;
|
||||
try {
|
||||
form.handleEvent(event);
|
||||
} catch (err) {
|
||||
|
|
|
@ -6,7 +6,7 @@ export default Controller.extend({
|
|||
builder: service('form'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.form = get(this, 'builder').form('intention');
|
||||
this.form = this.builder.form('intention');
|
||||
},
|
||||
setProperties: function(model) {
|
||||
const sourceName = get(model.item, 'SourceName');
|
||||
|
@ -35,11 +35,11 @@ export default Controller.extend({
|
|||
return template.replace(/{{term}}/g, term);
|
||||
},
|
||||
isUnique: function(term) {
|
||||
return !get(this, 'items').findBy('Name', term);
|
||||
return !this.items.findBy('Name', term);
|
||||
},
|
||||
change: function(e, value, item) {
|
||||
const event = get(this, 'dom').normalizeEvent(e, value);
|
||||
const form = get(this, 'form');
|
||||
const event = this.dom.normalizeEvent(e, value);
|
||||
const form = this.form;
|
||||
const target = event.target;
|
||||
|
||||
let name;
|
||||
|
@ -55,7 +55,7 @@ export default Controller.extend({
|
|||
name = get(target.value, 'Name');
|
||||
}
|
||||
// see if the name is already in the list
|
||||
match = get(this, 'items').filterBy('Name', name);
|
||||
match = this.items.filterBy('Name', name);
|
||||
if (match.length === 0) {
|
||||
// if its not make a new 'fake' Service that doesn't exist yet
|
||||
// and add it to the possible services to make an intention between
|
||||
|
|
|
@ -9,7 +9,7 @@ export default Controller.extend({
|
|||
json: true,
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this.form = get(this, 'builder').form('kv');
|
||||
this.form = this.builder.form('kv');
|
||||
},
|
||||
setProperties: function(model) {
|
||||
// essentially this replaces the data with changesets
|
||||
|
@ -26,8 +26,8 @@ export default Controller.extend({
|
|||
},
|
||||
actions: {
|
||||
change: function(e, value, item) {
|
||||
const event = get(this, 'dom').normalizeEvent(e, value);
|
||||
const form = get(this, 'form');
|
||||
const event = this.dom.normalizeEvent(e, value);
|
||||
const form = this.form;
|
||||
try {
|
||||
form.handleEvent(event);
|
||||
} catch (err) {
|
||||
|
@ -35,7 +35,7 @@ export default Controller.extend({
|
|||
let parent;
|
||||
switch (target.name) {
|
||||
case 'value':
|
||||
set(this.item, 'Value', get(this, 'encoder').execute(target.value));
|
||||
set(this.item, 'Value', this.encoder.execute(target.value));
|
||||
break;
|
||||
case 'additional':
|
||||
parent = get(this, 'parent.Key');
|
||||
|
@ -47,7 +47,7 @@ export default Controller.extend({
|
|||
// even if the user has selected code=off on another KV
|
||||
// ideally we would save the value per KV, but I'd like to not do that on the model
|
||||
// a set(this, 'json', valueFromSomeStorageJustForThisKV) would be added here
|
||||
set(this, 'json', !get(this, 'json'));
|
||||
set(this, 'json', !this.json);
|
||||
break;
|
||||
default:
|
||||
throw err;
|
||||
|
|
|
@ -16,7 +16,7 @@ export default Controller.extend(WithSearching, {
|
|||
},
|
||||
searchable: computed('items', function() {
|
||||
return get(this, 'searchables.kv')
|
||||
.add(get(this, 'items'))
|
||||
.add(this.items)
|
||||
.search(get(this, this.searchParams.kv));
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -14,21 +14,21 @@ export default Controller.extend(WithEventSource, WithSearching, WithHealthFilte
|
|||
},
|
||||
searchableHealthy: computed('healthy', function() {
|
||||
return get(this, 'searchables.healthyNode')
|
||||
.add(get(this, 'healthy'))
|
||||
.add(this.healthy)
|
||||
.search(get(this, this.searchParams.healthyNode));
|
||||
}),
|
||||
searchableUnhealthy: computed('unhealthy', function() {
|
||||
return get(this, 'searchables.unhealthyNode')
|
||||
.add(get(this, 'unhealthy'))
|
||||
.add(this.unhealthy)
|
||||
.search(get(this, this.searchParams.unhealthyNode));
|
||||
}),
|
||||
unhealthy: computed('filtered', function() {
|
||||
return get(this, 'filtered').filter(function(item) {
|
||||
return this.filtered.filter(function(item) {
|
||||
return get(item, 'isUnhealthy');
|
||||
});
|
||||
}),
|
||||
healthy: computed('filtered', function() {
|
||||
return get(this, 'filtered').filter(function(item) {
|
||||
return this.filtered.filter(function(item) {
|
||||
return get(item, 'isHealthy');
|
||||
});
|
||||
}),
|
||||
|
|
|
@ -25,20 +25,20 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
if (e.target.readyState === 1) {
|
||||
// OPEN
|
||||
if (get(e, 'error.errors.firstObject.status') === '404') {
|
||||
get(this, 'notify').add({
|
||||
this.notify.add({
|
||||
destroyOnClick: false,
|
||||
sticky: true,
|
||||
type: 'warning',
|
||||
action: 'update',
|
||||
});
|
||||
get(this, 'tomography').close();
|
||||
get(this, 'sessions').close();
|
||||
this.tomography.close();
|
||||
this.sessions.close();
|
||||
}
|
||||
}
|
||||
}),
|
||||
searchable: computed('items', function() {
|
||||
return get(this, 'searchables.nodeservice')
|
||||
.add(get(this, 'items'))
|
||||
.add(this.items)
|
||||
.search(get(this, this.searchParams.nodeservice));
|
||||
}),
|
||||
setProperties: function() {
|
||||
|
@ -55,7 +55,7 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
set(this, 'selectedTab', e.target.value);
|
||||
// Ensure tabular-collections sizing is recalculated
|
||||
// now it is visible in the DOM
|
||||
get(this, 'dom')
|
||||
this.dom
|
||||
.components('.tab-section input[type="radio"]:checked + div table')
|
||||
.forEach(function(item) {
|
||||
if (typeof item.didAppear === 'function') {
|
||||
|
|
|
@ -39,8 +39,8 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
},
|
||||
searchable: computed('items.[]', function() {
|
||||
return get(this, 'searchables.service')
|
||||
.add(get(this, 'items'))
|
||||
.search(get(this, 'terms'));
|
||||
.add(this.items)
|
||||
.search(this.terms);
|
||||
}),
|
||||
maxWidth: computed('{maxPassing,maxWarning,maxCritical}', function() {
|
||||
const PADDING = 32 * 3 + 13;
|
||||
|
@ -49,7 +49,7 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
}, PADDING);
|
||||
}),
|
||||
totalWidth: computed('maxWidth', function() {
|
||||
return widthDeclaration(get(this, 'maxWidth'));
|
||||
return widthDeclaration(this.maxWidth);
|
||||
}),
|
||||
remainingWidth: computed('maxWidth', function() {
|
||||
// maxWidth is the maximum width of the healthchecks column
|
||||
|
@ -57,24 +57,24 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
// take that off 50% (100% / number of fluid columns)
|
||||
// also we added a Type column which we've currently fixed to 100px
|
||||
// so again divide that by 2 and take it off each fluid column
|
||||
return htmlSafe(`width: calc(50% - ${Math.round(get(this, 'maxWidth') / 2)}px)`);
|
||||
return htmlSafe(`width: calc(50% - ${Math.round(this.maxWidth / 2)}px)`);
|
||||
}),
|
||||
maxPassing: computed('items.[]', function() {
|
||||
return max(get(this, 'items'), 'ChecksPassing');
|
||||
return max(this.items, 'ChecksPassing');
|
||||
}),
|
||||
maxWarning: computed('items.[]', function() {
|
||||
return max(get(this, 'items'), 'ChecksWarning');
|
||||
return max(this.items, 'ChecksWarning');
|
||||
}),
|
||||
maxCritical: computed('items.[]', function() {
|
||||
return max(get(this, 'items'), 'ChecksCritical');
|
||||
return max(this.items, 'ChecksCritical');
|
||||
}),
|
||||
passingWidth: computed('maxPassing', function() {
|
||||
return widthDeclaration(width(get(this, 'maxPassing')));
|
||||
return widthDeclaration(width(this.maxPassing));
|
||||
}),
|
||||
warningWidth: computed('maxWarning', function() {
|
||||
return widthDeclaration(width(get(this, 'maxWarning')));
|
||||
return widthDeclaration(width(this.maxWarning));
|
||||
}),
|
||||
criticalWidth: computed('maxCritical', function() {
|
||||
return widthDeclaration(width(get(this, 'maxCritical')));
|
||||
return widthDeclaration(width(this.maxCritical));
|
||||
}),
|
||||
});
|
||||
|
|
|
@ -16,13 +16,13 @@ export default Controller.extend(WithEventSource, {
|
|||
if (e.target.readyState === 1) {
|
||||
// OPEN
|
||||
if (get(e, 'error.errors.firstObject.status') === '404') {
|
||||
get(this, 'notify').add({
|
||||
this.notify.add({
|
||||
destroyOnClick: false,
|
||||
sticky: true,
|
||||
type: 'warning',
|
||||
action: 'update',
|
||||
});
|
||||
const proxy = get(this, 'proxy');
|
||||
const proxy = this.proxy;
|
||||
if (proxy) {
|
||||
proxy.close();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
if (e.target.readyState === 1) {
|
||||
// OPEN
|
||||
if (get(e, 'error.errors.firstObject.status') === '404') {
|
||||
get(this, 'notify').add({
|
||||
this.notify.add({
|
||||
destroyOnClick: false,
|
||||
sticky: true,
|
||||
type: 'warning',
|
||||
|
@ -36,7 +36,7 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
}),
|
||||
searchable: computed('items', function() {
|
||||
return get(this, 'searchables.serviceInstance')
|
||||
.add(get(this, 'items'))
|
||||
.add(this.items)
|
||||
.search(get(this, this.searchParams.serviceInstance));
|
||||
}),
|
||||
actions: {
|
||||
|
@ -44,7 +44,7 @@ export default Controller.extend(WithEventSource, WithSearching, {
|
|||
set(this, 'selectedTab', e.target.value);
|
||||
// Ensure tabular-collections sizing is recalculated
|
||||
// now it is visible in the DOM
|
||||
get(this, 'dom')
|
||||
this.dom
|
||||
.components('.tab-section input[type="radio"]:checked + div table')
|
||||
.forEach(function(item) {
|
||||
if (typeof item.didAppear === 'function') {
|
||||
|
|
|
@ -8,7 +8,7 @@ export default Controller.extend({
|
|||
timeout: service('timeout'),
|
||||
confirming: false,
|
||||
applyTransition: function() {
|
||||
const tick = get(this, 'timeout').tick;
|
||||
const tick = this.timeout.tick;
|
||||
set(this, 'confirming', true);
|
||||
tick().then(() => {
|
||||
set(this, 'confirming', false);
|
||||
|
@ -24,7 +24,7 @@ export default Controller.extend({
|
|||
}
|
||||
},
|
||||
change: function(e, value, item) {
|
||||
const event = get(this, 'dom').normalizeEvent(e, value);
|
||||
const event = this.dom.normalizeEvent(e, value);
|
||||
// TODO: Switch to using forms like the rest of the app
|
||||
// setting utils/form/builder for things to be done before we
|
||||
// can do that. For the moment just do things normally its a simple
|
||||
|
@ -35,14 +35,14 @@ export default Controller.extend({
|
|||
switch (target.name) {
|
||||
case 'client[blocking]':
|
||||
set(this, 'item.client.blocking', !blocking);
|
||||
this.send('update', get(this, 'item'));
|
||||
this.send('update', this.item);
|
||||
break;
|
||||
case 'urls[service]':
|
||||
if (typeof get(this, 'item.urls') === 'undefined') {
|
||||
set(this, 'item.urls', {});
|
||||
}
|
||||
set(this, 'item.urls.service', target.value);
|
||||
this.send('update', get(this, 'item'));
|
||||
this.send('update', this.item);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -12,20 +12,18 @@ const isWildcard = wildcard(routes);
|
|||
|
||||
export default Helper.extend({
|
||||
compute([targetRouteName, ...rest], namedArgs) {
|
||||
if (isWildcard(targetRouteName)) {
|
||||
rest = rest.map(function(item, i) {
|
||||
return item
|
||||
.split('/')
|
||||
.map(encodeURIComponent)
|
||||
.join('/');
|
||||
});
|
||||
}
|
||||
if (namedArgs.params) {
|
||||
return hrefTo(this, ...namedArgs.params);
|
||||
return hrefTo(this, namedArgs.params);
|
||||
} else {
|
||||
if (isWildcard(targetRouteName)) {
|
||||
const split = rest.map(function(item, i) {
|
||||
return item
|
||||
.split('/')
|
||||
.map(encodeURIComponent)
|
||||
.join('/');
|
||||
});
|
||||
return hrefTo(this, targetRouteName, ...split);
|
||||
} else {
|
||||
return hrefTo(this, targetRouteName, ...rest);
|
||||
}
|
||||
return hrefTo(this, [targetRouteName, ...rest]);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/*eslint ember/no-observers: "warn"*/
|
||||
// TODO: Remove ^
|
||||
import Helper from '@ember/component/helper';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { observer } from '@ember/object';
|
||||
|
@ -5,7 +7,7 @@ import { observer } from '@ember/object';
|
|||
export default Helper.extend({
|
||||
router: service('router'),
|
||||
compute(params) {
|
||||
return this.get('router').isActive(...params);
|
||||
return this.router.isActive(...params);
|
||||
},
|
||||
onURLChange: observer('router.currentURL', function() {
|
||||
this.recompute();
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { get } from '@ember/object';
|
||||
export function initialize(application) {
|
||||
const PowerSelectComponent = application.resolveRegistration('component:power-select');
|
||||
PowerSelectComponent.reopen({
|
||||
updateState: function(changes) {
|
||||
if (!get(this, 'isDestroyed')) {
|
||||
if (!this.isDestroyed) {
|
||||
return this._super(changes);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,11 +7,11 @@ export default Mixin.create(WithBlockingActions, {
|
|||
settings: service('settings'),
|
||||
actions: {
|
||||
use: function(item) {
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return this.feedback.execute(() => {
|
||||
// old style legacy ACLs don't have AccessorIDs
|
||||
// therefore set it to null, this way the frontend knows
|
||||
// to use legacy ACLs
|
||||
return get(this, 'settings')
|
||||
return this.settings
|
||||
.persist({
|
||||
token: {
|
||||
AccessorID: null,
|
||||
|
@ -25,28 +25,24 @@ export default Mixin.create(WithBlockingActions, {
|
|||
},
|
||||
// TODO: This is also used in tokens, probably an opportunity to dry this out
|
||||
logout: function(item) {
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return get(this, 'settings')
|
||||
.delete('token')
|
||||
.then(() => {
|
||||
// in this case we don't do the same as delete as we want to go to the new
|
||||
// dc.acls.tokens page. If we get there via the dc.acls redirect/rewrite
|
||||
// then we lose the flash message
|
||||
return this.transitionTo('dc.acls.tokens');
|
||||
});
|
||||
return this.feedback.execute(() => {
|
||||
return this.settings.delete('token').then(() => {
|
||||
// in this case we don't do the same as delete as we want to go to the new
|
||||
// dc.acls.tokens page. If we get there via the dc.acls redirect/rewrite
|
||||
// then we lose the flash message
|
||||
return this.transitionTo('dc.acls.tokens');
|
||||
});
|
||||
}, 'logout');
|
||||
},
|
||||
clone: function(item) {
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return get(this, 'repo')
|
||||
.clone(item)
|
||||
.then(item => {
|
||||
// cloning is similar to delete in that
|
||||
// if you clone from the listing page, stay on the listing page
|
||||
// whereas if you clone form another token, take me back to the listing page
|
||||
// so I can see it
|
||||
return this.afterDelete(...arguments);
|
||||
});
|
||||
return this.feedback.execute(() => {
|
||||
return this.repo.clone(item).then(item => {
|
||||
// cloning is similar to delete in that
|
||||
// if you clone from the listing page, stay on the listing page
|
||||
// whereas if you clone form another token, take me back to the listing page
|
||||
// so I can see it
|
||||
return this.afterDelete(...arguments);
|
||||
});
|
||||
}, 'clone');
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Mixin from '@ember/object/mixin';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { next } from '@ember/runloop';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
// TODO: Potentially move this to dom service
|
||||
const isOutside = function(element, e, doc = document) {
|
||||
|
@ -15,7 +14,7 @@ const isOutside = function(element, e, doc = document) {
|
|||
};
|
||||
|
||||
const handler = function(e) {
|
||||
const el = get(this, 'element');
|
||||
const el = this.element;
|
||||
if (isOutside(el, e)) {
|
||||
this.onblur(e);
|
||||
}
|
||||
|
@ -30,14 +29,14 @@ export default Mixin.create({
|
|||
onblur: function() {},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
const doc = get(this, 'dom').document();
|
||||
const doc = this.dom.document();
|
||||
next(this, () => {
|
||||
doc.addEventListener('click', this.handler);
|
||||
});
|
||||
},
|
||||
willDestroyElement: function() {
|
||||
this._super(...arguments);
|
||||
const doc = get(this, 'dom').document();
|
||||
const doc = this.dom.document();
|
||||
doc.removeEventListener('click', this.handler);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -10,7 +10,7 @@ import { get } from '@ember/object';
|
|||
*/
|
||||
export default Mixin.create({
|
||||
beforeModel: function() {
|
||||
get(this, 'repo').invalidate();
|
||||
this.repo.invalidate();
|
||||
},
|
||||
deactivate: function() {
|
||||
// TODO: This is dependent on ember-changeset
|
||||
|
|
|
@ -21,8 +21,8 @@ export default Mixin.create(WithBlockingActions, {
|
|||
actions: {
|
||||
invalidateSession: function(item) {
|
||||
const controller = this.controller;
|
||||
const repo = get(this, 'sessionRepo');
|
||||
return get(this, 'feedback').execute(() => {
|
||||
const repo = this.sessionRepo;
|
||||
return this.feedback.execute(() => {
|
||||
return repo.remove(item).then(() => {
|
||||
const item = get(controller, 'item');
|
||||
set(item, 'Session', null);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { REQUEST_CREATE, REQUEST_UPDATE } from 'consul-ui/adapters/application';
|
||||
|
||||
import Mixin from '@ember/object/mixin';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
|
@ -17,6 +15,8 @@ const normalizeServiceIdentities = function(items) {
|
|||
return policy;
|
||||
});
|
||||
};
|
||||
// Sometimes we get `Policies: null`, make null equal an empty array
|
||||
// and add an empty template
|
||||
const normalizePolicies = function(items) {
|
||||
return (items || []).map(function(item) {
|
||||
return {
|
||||
|
@ -47,24 +47,36 @@ const serializePolicies = function(items) {
|
|||
};
|
||||
|
||||
export default Mixin.create({
|
||||
handleSingleResponse: function(url, response, primary, slug) {
|
||||
response.Policies = normalizePolicies(response.Policies).concat(
|
||||
normalizeServiceIdentities(response.ServiceIdentities)
|
||||
);
|
||||
return this._super(url, response, primary, slug);
|
||||
//TODO: what about update and create?
|
||||
respondForQueryRecord: function(respond, query) {
|
||||
return this._super(function(cb) {
|
||||
return respond((headers, body) => {
|
||||
body.Policies = normalizePolicies(body.Policies).concat(
|
||||
normalizeServiceIdentities(body.ServiceIdentities)
|
||||
);
|
||||
return cb(headers, body);
|
||||
});
|
||||
}, query);
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
respondForQuery: function(respond, query) {
|
||||
return this._super(function(cb) {
|
||||
return respond(function(headers, body) {
|
||||
return cb(
|
||||
headers,
|
||||
body.map(function(item) {
|
||||
item.Policies = normalizePolicies(item.Policies).concat(
|
||||
normalizeServiceIdentities(item.ServiceIdentities)
|
||||
);
|
||||
return item;
|
||||
})
|
||||
);
|
||||
});
|
||||
}, query);
|
||||
},
|
||||
serialize: function(snapshot, options) {
|
||||
const data = this._super(...arguments);
|
||||
const name = params.type.modelName;
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
// falls through
|
||||
case REQUEST_CREATE:
|
||||
// ServiceIdentities serialization must happen first, or a copy taken
|
||||
data[name].ServiceIdentities = serializeServiceIdentities(data[name].Policies);
|
||||
data[name].Policies = minimizeModel(serializePolicies(data[name].Policies));
|
||||
break;
|
||||
}
|
||||
data.ServiceIdentities = serializeServiceIdentities(data.Policies);
|
||||
data.Policies = minimizeModel(serializePolicies(data.Policies));
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
import { REQUEST_CREATE, REQUEST_UPDATE } from 'consul-ui/adapters/application';
|
||||
|
||||
import Mixin from '@ember/object/mixin';
|
||||
|
||||
import minimizeModel from 'consul-ui/utils/minimizeModel';
|
||||
|
||||
export default Mixin.create({
|
||||
handleSingleResponse: function(url, response, primary, slug) {
|
||||
['Roles'].forEach(function(prop) {
|
||||
if (typeof response[prop] === 'undefined' || response[prop] === null) {
|
||||
response[prop] = [];
|
||||
}
|
||||
});
|
||||
return this._super(url, response, primary, slug);
|
||||
// TODO: what about update and create?
|
||||
respondForQueryRecord: function(respond, query) {
|
||||
return this._super(function(cb) {
|
||||
return respond((headers, body) => {
|
||||
body.Roles = typeof body.Roles === 'undefined' || body.Roles === null ? [] : body.Roles;
|
||||
return cb(headers, body);
|
||||
});
|
||||
}, query);
|
||||
},
|
||||
dataForRequest: function(params) {
|
||||
const name = params.type.modelName;
|
||||
respondForQuery: function(respond, query) {
|
||||
return this._super(function(cb) {
|
||||
return respond(function(headers, body) {
|
||||
return cb(
|
||||
headers,
|
||||
body.map(function(item) {
|
||||
item.Roles = typeof item.Roles === 'undefined' || item.Roles === null ? [] : item.Roles;
|
||||
return item;
|
||||
})
|
||||
);
|
||||
});
|
||||
}, query);
|
||||
},
|
||||
serialize: function(snapshot, options) {
|
||||
const data = this._super(...arguments);
|
||||
switch (params.requestType) {
|
||||
case REQUEST_UPDATE:
|
||||
// falls through
|
||||
case REQUEST_CREATE:
|
||||
data[name].Roles = minimizeModel(data[name].Roles);
|
||||
break;
|
||||
}
|
||||
data.Roles = minimizeModel(data.Roles);
|
||||
return data;
|
||||
},
|
||||
});
|
||||
|
|
|
@ -7,11 +7,11 @@ export default Mixin.create(WithBlockingActions, {
|
|||
settings: service('settings'),
|
||||
actions: {
|
||||
use: function(item) {
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return get(this, 'repo')
|
||||
return this.feedback.execute(() => {
|
||||
return this.repo
|
||||
.findBySlug(get(item, 'AccessorID'), this.modelFor('dc').dc.Name)
|
||||
.then(item => {
|
||||
return get(this, 'settings')
|
||||
return this.settings
|
||||
.persist({
|
||||
token: {
|
||||
AccessorID: get(item, 'AccessorID'),
|
||||
|
@ -28,21 +28,19 @@ export default Mixin.create(WithBlockingActions, {
|
|||
}, 'use');
|
||||
},
|
||||
logout: function(item) {
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return get(this, 'settings')
|
||||
.delete('token')
|
||||
.then(() => {
|
||||
// logging out is similar to delete in that
|
||||
// if you log out from the listing page, stay on the listing page
|
||||
// whereas if you logout from the detail page, take me back to the listing page
|
||||
return this.afterDelete(...arguments);
|
||||
});
|
||||
return this.feedback.execute(() => {
|
||||
return this.settings.delete('token').then(() => {
|
||||
// logging out is similar to delete in that
|
||||
// if you log out from the listing page, stay on the listing page
|
||||
// whereas if you logout from the detail page, take me back to the listing page
|
||||
return this.afterDelete(...arguments);
|
||||
});
|
||||
}, 'logout');
|
||||
},
|
||||
clone: function(item) {
|
||||
let cloned;
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return get(this, 'repo')
|
||||
return this.feedback.execute(() => {
|
||||
return this.repo
|
||||
.clone(item)
|
||||
.then(item => {
|
||||
cloned = item;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Mixin from '@ember/object/mixin';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
/** With Blocking Actions
|
||||
* This mixin contains common write actions (Create Update Delete) for routes.
|
||||
* It could also be an Route to extend but decoration seems to be more sense right now.
|
||||
|
@ -20,7 +20,7 @@ export default Mixin.create({
|
|||
_feedback: service('feedback'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
const feedback = get(this, '_feedback');
|
||||
const feedback = this._feedback;
|
||||
const route = this;
|
||||
set(this, 'feedback', {
|
||||
execute: function(cb, type, error) {
|
||||
|
@ -69,13 +69,11 @@ export default Mixin.create({
|
|||
return this.afterUpdate(...arguments);
|
||||
},
|
||||
create: function(item) {
|
||||
return get(this, 'feedback').execute(
|
||||
return this.feedback.execute(
|
||||
() => {
|
||||
return get(this, 'repo')
|
||||
.persist(item)
|
||||
.then(item => {
|
||||
return this.afterCreate(...arguments);
|
||||
});
|
||||
return this.repo.persist(item).then(item => {
|
||||
return this.afterCreate(...arguments);
|
||||
});
|
||||
},
|
||||
'create',
|
||||
(type, e) => {
|
||||
|
@ -84,13 +82,11 @@ export default Mixin.create({
|
|||
);
|
||||
},
|
||||
update: function(item) {
|
||||
return get(this, 'feedback').execute(
|
||||
return this.feedback.execute(
|
||||
() => {
|
||||
return get(this, 'repo')
|
||||
.persist(item)
|
||||
.then(() => {
|
||||
return this.afterUpdate(...arguments);
|
||||
});
|
||||
return this.repo.persist(item).then(() => {
|
||||
return this.afterUpdate(...arguments);
|
||||
});
|
||||
},
|
||||
'update',
|
||||
(type, e) => {
|
||||
|
@ -99,13 +95,11 @@ export default Mixin.create({
|
|||
);
|
||||
},
|
||||
delete: function(item) {
|
||||
return get(this, 'feedback').execute(
|
||||
return this.feedback.execute(
|
||||
() => {
|
||||
return get(this, 'repo')
|
||||
.remove(item)
|
||||
.then(() => {
|
||||
return this.afterDelete(...arguments);
|
||||
});
|
||||
return this.repo.remove(item).then(() => {
|
||||
return this.afterDelete(...arguments);
|
||||
});
|
||||
},
|
||||
'delete',
|
||||
(type, e) => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Mixin from '@ember/object/mixin';
|
||||
import { set } from '@ember/object';
|
||||
import { computed as catchable } from 'consul-ui/computed/catchable';
|
||||
import purify from 'consul-ui/utils/computed/purify';
|
||||
|
||||
|
@ -9,13 +10,23 @@ export default Mixin.create(WithListeners, {
|
|||
const _model = {};
|
||||
Object.keys(model).forEach(prop => {
|
||||
// here (see comment below on deleting)
|
||||
if (this[prop] && this[prop].isDescriptor) {
|
||||
_model[`${PREFIX}${prop}`] = model[prop];
|
||||
const meta = this.constructor.metaForProperty(prop) || {};
|
||||
if (model[prop] && typeof model[prop].addEventListener === 'function') {
|
||||
let meta;
|
||||
// TODO: metaForProperty throws an error if the property is not
|
||||
// computed-like, this is far from ideal but happy with this
|
||||
// until we can find a better way in an ember post 2.18 world
|
||||
// of finding out if a property is computed or not
|
||||
// (or until we switch all this out for <DataSource /> compoments
|
||||
try {
|
||||
meta = this.constructor.metaForProperty(prop);
|
||||
} catch (e) {
|
||||
meta = {};
|
||||
}
|
||||
if (typeof meta.catch === 'function') {
|
||||
if (typeof _model[`${PREFIX}${prop}`].addEventListener === 'function') {
|
||||
this.listen(_model[`_${prop}`], 'error', meta.catch.bind(this));
|
||||
}
|
||||
_model[`${PREFIX}${prop}`] = model[prop];
|
||||
this.listen(_model[`_${prop}`], 'error', meta.catch.bind(this));
|
||||
} else {
|
||||
_model[prop] = model[prop];
|
||||
}
|
||||
} else {
|
||||
_model[prop] = model[prop];
|
||||
|
@ -33,7 +44,10 @@ export default Mixin.create(WithListeners, {
|
|||
// setProperties will be called the next time we enter the Route so this
|
||||
// is ok for what we need and means that the above conditional works
|
||||
// as expected (see 'here' comment above)
|
||||
delete this[prop];
|
||||
// delete this[prop];
|
||||
// TODO: Check that nulling this out instead of deleting is fine
|
||||
// pretty sure it is as above is just a falsey check
|
||||
set(this, prop, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ export default Mixin.create({
|
|||
set(this, key, obj[key] != '' ? obj[key] : null);
|
||||
});
|
||||
set(this, 'filters', {
|
||||
...this.get('filters'),
|
||||
...this.filters,
|
||||
...obj,
|
||||
});
|
||||
},
|
||||
|
|
|
@ -2,13 +2,12 @@ import Controller from '@ember/controller';
|
|||
import Component from '@ember/component';
|
||||
import Mixin from '@ember/object/mixin';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
export default Mixin.create({
|
||||
dom: service('dom'),
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
this._listeners = get(this, 'dom').listeners();
|
||||
this._listeners = this.dom.listeners();
|
||||
let teardown = ['willDestroy'];
|
||||
if (this instanceof Component) {
|
||||
teardown = ['willDestroyElement'];
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import Mixin from '@ember/object/mixin';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get } from '@ember/object';
|
||||
import { assert } from '@ember/debug';
|
||||
export default Mixin.create({
|
||||
dom: service('dom'),
|
||||
|
@ -18,18 +17,14 @@ export default Mixin.create({
|
|||
},
|
||||
didInsertElement: function() {
|
||||
this._super(...arguments);
|
||||
get(this, 'dom')
|
||||
.viewport()
|
||||
.addEventListener('resize', this.handler, false);
|
||||
this.dom.viewport().addEventListener('resize', this.handler, false);
|
||||
this.didAppear();
|
||||
},
|
||||
didAppear: function() {
|
||||
this.handler({ target: get(this, 'dom').viewport() });
|
||||
this.handler({ target: this.dom.viewport() });
|
||||
},
|
||||
willDestroyElement: function() {
|
||||
get(this, 'dom')
|
||||
.viewport()
|
||||
.removeEventListener('resize', this.handler, false);
|
||||
this.dom.viewport().removeEventListener('resize', this.handler, false);
|
||||
this._super(...arguments);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import Mixin from '@ember/object/mixin';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { get, set } from '@ember/object';
|
||||
import { set } from '@ember/object';
|
||||
import WithListeners from 'consul-ui/mixins/with-listeners';
|
||||
/**
|
||||
* WithSearching mostly depends on a `searchParams` object which must be set
|
||||
|
@ -22,7 +22,7 @@ export default Mixin.create(WithListeners, {
|
|||
this.searchables = {};
|
||||
Object.keys(params).forEach(type => {
|
||||
const key = params[type];
|
||||
this.searchables[type] = get(this, 'builder').searchable(type);
|
||||
this.searchables[type] = this.builder.searchable(type);
|
||||
this.listen(this.searchables[type], 'change', e => {
|
||||
const value = e.target.value;
|
||||
set(this, key, value === '' ? null : value);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
import { next } from '@ember/runloop';
|
||||
import { Promise } from 'rsvp';
|
||||
|
||||
|
@ -19,11 +18,11 @@ export default Route.extend(WithBlockingActions, {
|
|||
settings: service('settings'),
|
||||
actions: {
|
||||
loading: function(transition, originRoute) {
|
||||
const $root = get(this, 'dom').root();
|
||||
const $root = this.dom.root();
|
||||
let dc = null;
|
||||
if (originRoute.routeName !== 'dc') {
|
||||
const model = this.modelFor('dc') || { dcs: null, dc: { Name: null } };
|
||||
dc = get(this, 'repo').getActive(model.dc.Name, model.dcs);
|
||||
dc = this.repo.getActive(model.dc.Name, model.dcs);
|
||||
}
|
||||
hash({
|
||||
loading: !$root.classList.contains('ember-loading'),
|
||||
|
@ -66,23 +65,21 @@ export default Route.extend(WithBlockingActions, {
|
|||
// if a token has not been sent at all, it just gives you a 200 with an empty dataset
|
||||
const model = this.modelFor('dc');
|
||||
if (error.status === '403') {
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return get(this, 'settings')
|
||||
.delete('token')
|
||||
.then(() => {
|
||||
return Promise.reject(this.transitionTo('dc.acls.tokens', model.dc.Name));
|
||||
});
|
||||
return this.feedback.execute(() => {
|
||||
return this.settings.delete('token').then(() => {
|
||||
return Promise.reject(this.transitionTo('dc.acls.tokens', model.dc.Name));
|
||||
});
|
||||
}, 'authorize');
|
||||
}
|
||||
if (error.status === '') {
|
||||
error.message = 'Error';
|
||||
}
|
||||
const $root = get(this, 'dom').root();
|
||||
const $root = this.dom.root();
|
||||
hash({
|
||||
error: error,
|
||||
dc:
|
||||
error.status.toString().indexOf('5') !== 0
|
||||
? get(this, 'repo').getActive()
|
||||
? this.repo.getActive()
|
||||
: model && model.dc
|
||||
? model.dc
|
||||
: { Name: 'Error' },
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
export default Route.extend({
|
||||
repo: service('repository/dc'),
|
||||
settings: service('settings'),
|
||||
model: function(params) {
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
return hash({
|
||||
dcs: repo.findAll(),
|
||||
}).then(function(model) {
|
||||
|
|
|
@ -9,32 +9,30 @@ export default Route.extend(WithBlockingActions, {
|
|||
actions: {
|
||||
authorize: function(secret) {
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
return get(this, 'feedback').execute(() => {
|
||||
return get(this, 'repo')
|
||||
.self(secret, dc)
|
||||
.then(item => {
|
||||
return get(this, 'settings')
|
||||
.persist({
|
||||
token: {
|
||||
AccessorID: get(item, 'AccessorID'),
|
||||
SecretID: secret,
|
||||
},
|
||||
})
|
||||
.then(item => {
|
||||
// a null AccessorID means we are in legacy mode
|
||||
// take the user to the legacy acls
|
||||
// otherwise just refresh the page
|
||||
if (get(item, 'token.AccessorID') === null) {
|
||||
// returning false for a feedback action means even though
|
||||
// its successful, please skip this notification and don't display it
|
||||
return this.transitionTo('dc.acls').then(function() {
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
this.refresh();
|
||||
}
|
||||
});
|
||||
});
|
||||
return this.feedback.execute(() => {
|
||||
return this.repo.self(secret, dc).then(item => {
|
||||
return this.settings
|
||||
.persist({
|
||||
token: {
|
||||
AccessorID: get(item, 'AccessorID'),
|
||||
SecretID: secret,
|
||||
},
|
||||
})
|
||||
.then(item => {
|
||||
// a null AccessorID means we are in legacy mode
|
||||
// take the user to the legacy acls
|
||||
// otherwise just refresh the page
|
||||
if (get(item, 'token.AccessorID') === null) {
|
||||
// returning false for a feedback action means even though
|
||||
// its successful, please skip this notification and don't display it
|
||||
return this.transitionTo('dc.acls').then(function() {
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
this.refresh();
|
||||
}
|
||||
});
|
||||
});
|
||||
}, 'authorize');
|
||||
},
|
||||
},
|
||||
|
|
|
@ -9,10 +9,10 @@ export default Route.extend(WithAclActions, {
|
|||
templateName: 'dc/acls/edit',
|
||||
repo: service('repository/acl'),
|
||||
beforeModel: function() {
|
||||
get(this, 'repo').invalidate();
|
||||
this.repo.invalidate();
|
||||
},
|
||||
model: function(params) {
|
||||
this.item = get(this, 'repo').create();
|
||||
this.item = this.repo.create();
|
||||
set(this.item, 'Datacenter', this.modelFor('dc').dc.Name);
|
||||
return hash({
|
||||
create: true,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import WithAclActions from 'consul-ui/mixins/acl/with-actions';
|
||||
|
||||
|
@ -11,7 +10,7 @@ export default Route.extend(WithAclActions, {
|
|||
model: function(params) {
|
||||
return hash({
|
||||
isLoading: false,
|
||||
item: get(this, 'repo').findBySlug(params.id, this.modelFor('dc').dc.Name),
|
||||
item: this.repo.findBySlug(params.id, this.modelFor('dc').dc.Name),
|
||||
types: ['management', 'client'],
|
||||
});
|
||||
},
|
||||
|
|
|
@ -15,24 +15,22 @@ export default Route.extend(WithAclActions, {
|
|||
},
|
||||
},
|
||||
beforeModel: function(transition) {
|
||||
return get(this, 'settings')
|
||||
.findBySlug('token')
|
||||
.then(token => {
|
||||
// If you don't have a token set or you have a
|
||||
// token set with AccessorID set to not null (new ACL mode)
|
||||
// then rewrite to the new acls
|
||||
if (!token || get(token, 'AccessorID') !== null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls.tokens');
|
||||
}
|
||||
});
|
||||
return this.settings.findBySlug('token').then(token => {
|
||||
// If you don't have a token set or you have a
|
||||
// token set with AccessorID set to not null (new ACL mode)
|
||||
// then rewrite to the new acls
|
||||
if (!token || get(token, 'AccessorID') !== null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls.tokens');
|
||||
}
|
||||
});
|
||||
},
|
||||
model: function(params) {
|
||||
return hash({
|
||||
isLoading: false,
|
||||
items: get(this, 'repo').findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
token: get(this, 'settings').findBySlug('token'),
|
||||
items: this.repo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
token: this.settings.findBySlug('token'),
|
||||
});
|
||||
},
|
||||
setupController: function(controller, model) {
|
||||
|
|
|
@ -10,7 +10,7 @@ export default SingleRoute.extend(WithPolicyActions, {
|
|||
tokenRepo: service('repository/token'),
|
||||
model: function(params) {
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
const tokenRepo = get(this, 'tokenRepo');
|
||||
const tokenRepo = this.tokenRepo;
|
||||
return this._super(...arguments).then(model => {
|
||||
return hash({
|
||||
...model,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import WithPolicyActions from 'consul-ui/mixins/policy/with-actions';
|
||||
|
||||
|
@ -14,7 +13,7 @@ export default Route.extend(WithPolicyActions, {
|
|||
},
|
||||
},
|
||||
model: function(params) {
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
return hash({
|
||||
...repo.status({
|
||||
items: repo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
|
|
|
@ -10,7 +10,7 @@ export default SingleRoute.extend(WithRoleActions, {
|
|||
tokenRepo: service('repository/token'),
|
||||
model: function(params) {
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
const tokenRepo = get(this, 'tokenRepo');
|
||||
const tokenRepo = this.tokenRepo;
|
||||
return this._super(...arguments).then(model => {
|
||||
return hash({
|
||||
...model,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import WithRoleActions from 'consul-ui/mixins/role/with-actions';
|
||||
|
||||
|
@ -14,7 +13,7 @@ export default Route.extend(WithRoleActions, {
|
|||
},
|
||||
},
|
||||
model: function(params) {
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
return hash({
|
||||
...repo.status({
|
||||
items: repo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import SingleRoute from 'consul-ui/routing/single';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import WithTokenActions from 'consul-ui/mixins/token/with-actions';
|
||||
|
||||
|
@ -13,7 +12,7 @@ export default SingleRoute.extend(WithTokenActions, {
|
|||
return hash({
|
||||
...model,
|
||||
...{
|
||||
token: get(this, 'settings').findBySlug('token'),
|
||||
token: this.settings.findBySlug('token'),
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,26 +13,24 @@ export default Route.extend(WithTokenActions, {
|
|||
},
|
||||
},
|
||||
beforeModel: function(transition) {
|
||||
return get(this, 'settings')
|
||||
.findBySlug('token')
|
||||
.then(token => {
|
||||
// If you have a token set with AccessorID set to null (legacy mode)
|
||||
// then rewrite to the old acls
|
||||
if (token && get(token, 'AccessorID') === null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls');
|
||||
}
|
||||
});
|
||||
return this.settings.findBySlug('token').then(token => {
|
||||
// If you have a token set with AccessorID set to null (legacy mode)
|
||||
// then rewrite to the old acls
|
||||
if (token && get(token, 'AccessorID') === null) {
|
||||
// If you return here, you get a TransitionAborted error in the tests only
|
||||
// everything works fine either way checking things manually
|
||||
this.replaceWith('dc.acls');
|
||||
}
|
||||
});
|
||||
},
|
||||
model: function(params) {
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
return hash({
|
||||
...repo.status({
|
||||
items: repo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
}),
|
||||
isLoading: false,
|
||||
token: get(this, 'settings').findBySlug('token'),
|
||||
token: this.settings.findBySlug('token'),
|
||||
});
|
||||
},
|
||||
setupController: function(controller, model) {
|
||||
|
|
|
@ -9,16 +9,16 @@ export default Route.extend(WithIntentionActions, {
|
|||
repo: service('repository/intention'),
|
||||
servicesRepo: service('repository/service'),
|
||||
beforeModel: function() {
|
||||
get(this, 'repo').invalidate();
|
||||
this.repo.invalidate();
|
||||
},
|
||||
model: function(params) {
|
||||
this.item = get(this, 'repo').create();
|
||||
this.item = this.repo.create();
|
||||
set(this.item, 'Datacenter', this.modelFor('dc').dc.Name);
|
||||
return hash({
|
||||
create: true,
|
||||
isLoading: false,
|
||||
item: this.item,
|
||||
items: get(this, 'servicesRepo').findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
items: this.servicesRepo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
intents: ['allow', 'deny'],
|
||||
}).then(function(model) {
|
||||
return {
|
||||
|
|
|
@ -11,8 +11,8 @@ export default Route.extend(WithAclActions, {
|
|||
model: function(params) {
|
||||
return hash({
|
||||
isLoading: false,
|
||||
item: get(this, 'repo').findBySlug(params.id, this.modelFor('dc').dc.Name),
|
||||
items: get(this, 'servicesRepo').findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
item: this.repo.findBySlug(params.id, this.modelFor('dc').dc.Name),
|
||||
items: this.servicesRepo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
intents: ['allow', 'deny'],
|
||||
}).then(function(model) {
|
||||
return {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
import WithIntentionActions from 'consul-ui/mixins/intention/with-actions';
|
||||
|
||||
|
@ -15,7 +14,7 @@ export default Route.extend(WithIntentionActions, {
|
|||
},
|
||||
model: function(params) {
|
||||
return hash({
|
||||
items: get(this, 'repo').findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
items: this.repo.findAllByDatacenter(this.modelFor('dc').dc.Name),
|
||||
});
|
||||
},
|
||||
setupController: function(controller, model) {
|
||||
|
|
|
@ -8,11 +8,11 @@ export default Route.extend(WithKvActions, {
|
|||
templateName: 'dc/kv/edit',
|
||||
repo: service('repository/kv'),
|
||||
beforeModel: function() {
|
||||
get(this, 'repo').invalidate();
|
||||
this.repo.invalidate();
|
||||
},
|
||||
model: function(params) {
|
||||
const key = params.key || '/';
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
this.item = repo.create();
|
||||
set(this.item, 'Datacenter', dc);
|
||||
|
|
|
@ -12,7 +12,7 @@ export default Route.extend(WithKvActions, {
|
|||
model: function(params) {
|
||||
const key = params.key;
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
return hash({
|
||||
isLoading: false,
|
||||
parent: repo.findBySlug(ascend(key, 1) || '/', dc),
|
||||
|
@ -25,7 +25,7 @@ export default Route.extend(WithKvActions, {
|
|||
return hash({
|
||||
...model,
|
||||
...{
|
||||
session: get(this, 'sessionRepo').findByKey(session, dc),
|
||||
session: this.sessionRepo.findByKey(session, dc),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ export default Route.extend(WithKvActions, {
|
|||
model: function(params) {
|
||||
let key = params.key || '/';
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
return hash({
|
||||
isLoading: false,
|
||||
parent: repo.findBySlug(key, dc),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
export default Route.extend({
|
||||
repo: service('repository/node'),
|
||||
|
@ -14,8 +13,8 @@ export default Route.extend({
|
|||
model: function(params) {
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
return hash({
|
||||
items: get(this, 'repo').findAllByDatacenter(dc),
|
||||
leader: get(this, 'repo').findByLeader(dc),
|
||||
items: this.repo.findAllByDatacenter(dc),
|
||||
leader: this.repo.findByLeader(dc),
|
||||
});
|
||||
},
|
||||
setupController: function(controller, model) {
|
||||
|
|
|
@ -19,9 +19,9 @@ export default Route.extend(WithBlockingActions, {
|
|||
const dc = this.modelFor('dc').dc.Name;
|
||||
const name = params.name;
|
||||
return hash({
|
||||
item: get(this, 'repo').findBySlug(name, dc),
|
||||
tomography: get(this, 'coordinateRepo').findAllByNode(name, dc),
|
||||
sessions: get(this, 'sessionRepo').findByNode(name, dc),
|
||||
item: this.repo.findBySlug(name, dc),
|
||||
tomography: this.coordinateRepo.findAllByNode(name, dc),
|
||||
sessions: this.sessionRepo.findByNode(name, dc),
|
||||
});
|
||||
},
|
||||
setupController: function(controller, model) {
|
||||
|
@ -31,8 +31,8 @@ export default Route.extend(WithBlockingActions, {
|
|||
invalidateSession: function(item) {
|
||||
const dc = this.modelFor('dc').dc.Name;
|
||||
const controller = this.controller;
|
||||
const repo = get(this, 'sessionRepo');
|
||||
return get(this, 'feedback').execute(() => {
|
||||
const repo = this.sessionRepo;
|
||||
return this.feedback.execute(() => {
|
||||
const node = get(item, 'Node');
|
||||
return repo.remove(item).then(() => {
|
||||
return repo.findByNode(node, dc).then(function(sessions) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Route from '@ember/routing/route';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { hash } from 'rsvp';
|
||||
import { get } from '@ember/object';
|
||||
|
||||
export default Route.extend({
|
||||
repo: service('repository/service'),
|
||||
|
@ -16,7 +15,7 @@ export default Route.extend({
|
|||
},
|
||||
},
|
||||
model: function(params) {
|
||||
const repo = get(this, 'repo');
|
||||
const repo = this.repo;
|
||||
let terms = params.s || '';
|
||||
// we check for the old style `status` variable here
|
||||
// and convert it to the new style filter=status:critical
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue