From 55bc45832e0a259831b5f250379634cb540d900c Mon Sep 17 00:00:00 2001 From: John Cowen Date: Wed, 6 Jun 2018 12:00:25 +0100 Subject: [PATCH] Tie up real endpoints --- ui-v2/app/adapters/intention.js | 28 +++++++++++- ui-v2/app/controllers/dc/intentions/edit.js | 12 +++--- ui-v2/app/models/intention.js | 16 +++++-- ui-v2/app/serializers/intention.js | 3 +- ui-v2/app/utils/http/method.js | 1 + ui-v2/app/utils/model/writable.js | 11 +++++ ui-v2/app/validations/intention.js | 6 +++ ui-v2/tests/unit/utils/model/writable-test.js | 43 +++++++++++++++++++ 8 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 ui-v2/app/utils/model/writable.js create mode 100644 ui-v2/app/validations/intention.js create mode 100644 ui-v2/tests/unit/utils/model/writable-test.js diff --git a/ui-v2/app/adapters/intention.js b/ui-v2/app/adapters/intention.js index 486e891429..cd0299d96b 100644 --- a/ui-v2/app/adapters/intention.js +++ b/ui-v2/app/adapters/intention.js @@ -1,7 +1,12 @@ -import Adapter, { DATACENTER_KEY as API_DATACENTER_KEY } from './application'; +import Adapter, { + REQUEST_CREATE, + REQUEST_UPDATE, + DATACENTER_KEY 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'; export default Adapter.extend({ urlForQuery: function(query, modelName) { @@ -33,6 +38,14 @@ export default Adapter.extend({ ).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; if (status === HTTP_OK) { @@ -40,7 +53,9 @@ export default Adapter.extend({ switch (true) { case this.isQueryRecord(url): case this.isUpdateRecord(url): - // case this.isCreateRecord(url): + // TODO: We just need to upgrade this entire API to + // use a full request-like object + case this.isCreateRecord(url, requestData.method): response = { ...response, ...{ @@ -61,4 +76,13 @@ export default Adapter.extend({ } 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; + }, }); diff --git a/ui-v2/app/controllers/dc/intentions/edit.js b/ui-v2/app/controllers/dc/intentions/edit.js index f085a95c60..ad433645a8 100644 --- a/ui-v2/app/controllers/dc/intentions/edit.js +++ b/ui-v2/app/controllers/dc/intentions/edit.js @@ -1,12 +1,13 @@ import Controller from '@ember/controller'; import { get, set } from '@ember/object'; -// import Changeset from 'ember-changeset'; -// import validations from 'consul-ui/validations/acl'; -// import lookupValidator from 'ember-changeset-validations'; +import Changeset from 'ember-changeset'; +import lookupValidator from 'ember-changeset-validations'; + +import validations from 'consul-ui/validations/intention'; export default Controller.extend({ setProperties: function(model) { - this.changeset = model.item; //new Changeset(model.item, lookupValidator(validations), validations); + this.changeset = new Changeset(model.item, lookupValidator(validations), validations); this._super({ ...model, ...{ @@ -18,15 +19,16 @@ export default Controller.extend({ }, actions: { change: function(e, value, _target) { + // normalize back to standard event const target = e.target || { ..._target, ...{ name: e, value: value } }; switch (target.name) { case 'Action': set(this.changeset, target.name, target.value); + console.log(target.name, target.value, get(this.changeset, target.name)); break; case 'SourceName': case 'DestinationName': set(this.changeset, target.name, get(target.value, 'Name')); - set(this.item, target.name, get(target.value, 'Name')); set(this, target.name, target.value); break; } diff --git a/ui-v2/app/models/intention.js b/ui-v2/app/models/intention.js index 43a9bb19eb..2937ff2248 100644 --- a/ui-v2/app/models/intention.js +++ b/ui-v2/app/models/intention.js @@ -1,10 +1,10 @@ import Model from 'ember-data/model'; import attr from 'ember-data/attr'; +import writable from 'consul-ui/utils/model/writable'; export const PRIMARY_KEY = 'uid'; export const SLUG_KEY = 'ID'; - -export default Model.extend({ +const model = Model.extend({ [PRIMARY_KEY]: attr('string'), [SLUG_KEY]: attr('string'), Description: attr('string'), @@ -12,8 +12,8 @@ export default Model.extend({ SourceName: attr('string'), DestinationName: attr('string'), Precedence: attr('number'), - SourceType: attr('string'), - Action: attr('string'), + SourceType: attr('string', { defaultValue: 'consul' }), + Action: attr('string', { defaultValue: 'deny' }), DefaultAddr: attr('string'), DefaultPort: attr('number'), Meta: attr(), @@ -23,3 +23,11 @@ export default Model.extend({ CreateIndex: attr('number'), ModifyIndex: attr('number'), }); +export const ATTRS = writable(model, [ + 'Action', + 'SourceName', + 'DestinationName', + 'SourceType', + 'Description', +]); +export default model; diff --git a/ui-v2/app/serializers/intention.js b/ui-v2/app/serializers/intention.js index d70f61c3f6..129c36ab66 100644 --- a/ui-v2/app/serializers/intention.js +++ b/ui-v2/app/serializers/intention.js @@ -1,6 +1,7 @@ import Serializer from './application'; -import { PRIMARY_KEY } from 'consul-ui/models/intention'; +import { PRIMARY_KEY, ATTRS } from 'consul-ui/models/intention'; export default Serializer.extend({ primaryKey: PRIMARY_KEY, + attrs: ATTRS, }); diff --git a/ui-v2/app/utils/http/method.js b/ui-v2/app/utils/http/method.js index a8da261ae3..d7c44593c4 100644 --- a/ui-v2/app/utils/http/method.js +++ b/ui-v2/app/utils/http/method.js @@ -1,2 +1,3 @@ export const PUT = 'PUT'; export const DELETE = 'DELETE'; +export const POST = 'POST'; diff --git a/ui-v2/app/utils/model/writable.js b/ui-v2/app/utils/model/writable.js new file mode 100644 index 0000000000..664401078f --- /dev/null +++ b/ui-v2/app/utils/model/writable.js @@ -0,0 +1,11 @@ +export default function(model, props, attr = {}) { + model.eachAttribute(function(item) { + attr[item] = { + ...attr[item], + ...{ + serialize: props.indexOf(item) !== -1, + }, + }; + }); + return attr; +} diff --git a/ui-v2/app/validations/intention.js b/ui-v2/app/validations/intention.js new file mode 100644 index 0000000000..922ba9e413 --- /dev/null +++ b/ui-v2/app/validations/intention.js @@ -0,0 +1,6 @@ +import { validatePresence, validateLength } from 'ember-changeset-validations/validators'; +export default { + SourceName: [validatePresence(true), validateLength({ min: 1 })], + DestinationName: [validatePresence(true), validateLength({ min: 1 })], + Action: validatePresence(true), +}; diff --git a/ui-v2/tests/unit/utils/model/writable-test.js b/ui-v2/tests/unit/utils/model/writable-test.js new file mode 100644 index 0000000000..f3b4a5494b --- /dev/null +++ b/ui-v2/tests/unit/utils/model/writable-test.js @@ -0,0 +1,43 @@ +import writable from 'consul-ui/utils/model/writable'; +import { module, test } from 'qunit'; + +module('Unit | Utility | model/writable'); + +test('it correctly marks attrs as serialize:true|false', function(assert) { + const yes = { + Props: true, + That: true, + Should: true, + Be: true, + Writable: true, + }; + const no = { + Others: true, + Read: true, + Only: true, + }; + const expectedYes = Object.keys(yes); + const expectedNo = Object.keys(no); + const model = { + eachAttribute: function(cb) { + expectedYes.concat(expectedNo).forEach(function(item) { + cb(item, {}); // we aren't testing the meta here, just use the same api + }); + }, + }; + let attrs = writable(model, Object.keys(yes)); + const actualYes = Object.keys(attrs).filter(item => attrs[item].serialize); + const actualNo = Object.keys(attrs).filter(item => !attrs[item].serialize); + assert.deepEqual(actualYes, expectedYes, 'writable props are marked as serializable'); + assert.deepEqual(actualNo, expectedNo, 'writable props are marked as not serializable'); + attrs = writable(model, Object.keys(yes), { + Props: { + another: 'property', + }, + }); + assert.equal( + attrs.Props.another, + 'property', + 'previous attrs objects can be passed without being overwritten' + ); +});