Merge branch 'main' into feat-radio-helper-text

This commit is contained in:
Dharini Jeeva authored and GitHub committed 2022-01-19 11:23:46 -08:00
commit e6928fe66f
9 files changed
+161 -39

No files matched your search

+30 -8
View File
@@ -263,14 +263,36 @@ export default class ApplicationAdapter extends RESTAdapter.extend(
source: { pointer: '/data' },
};
// Normalize field-specific errors, if any.
const errors = fieldErrors.map((error) => ({
detail: error.description,
// Ember Data cannot handle errors on nested attributes, so these are
// flattened (e.g. `attributes.foobar` becomes `attributes_foobar`).
// To capture these errors, add read-only fields on the model
// corresponding to the underscored field name.
source: { pointer: `/data/attributes/${error.name.replace('.', '_')}` },
}));
const errors = fieldErrors.flatMap((error) => {
const newValue = [
{
detail: error.description,
// Ember Data cannot handle errors on nested attributes, so these are
// flattened (e.g. `attributes.foobar` becomes `attributes_foobar`).
// To capture these errors, add read-only fields on the model
// corresponding to the underscored field name.
source: {
pointer: `/data/attributes/${error.name.replace('.', '_')}`,
},
},
];
if (error.name.includes('attributes.')) {
newValue.push({
detail: error.description,
// Going forward, nested attributes will be hoisted. Thus "attributes."
// must be stripped from the error name key. Until all models are
// transitioned away from model fragments, however, both this and the
// prior error key mappings are necessary.
source: {
pointer: `/data/attributes/${error.name.replace(
'attributes.',
''
)}`,
},
});
}
return newValue;
});
// Return a list of JSON API errors rooted under the `errors` key.
return {
errors: [baseError, ...errors],
@@ -1,9 +0,0 @@
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
export default class FragmentTargetAttributesModel extends Fragment {
@attr('number', {
description: 'The default port a target should use if present.',
})
default_port;
}
+7 -6
View File
@@ -1,15 +1,16 @@
import GeneratedTargetModel from '../generated/models/target';
import { fragment, fragmentArray } from 'ember-data-model-fragments/attributes';
import { attr } from '@ember-data/model';
import { fragmentArray } from 'ember-data-model-fragments/attributes';
import { computed } from '@ember/object';
export default class TargetModel extends GeneratedTargetModel {
// =attributes
/**
* Attributes of this resource, if any, represented as a JSON fragment.
* @type {FragmentTargetAttributesModel}
*/
@fragment('fragment-target-attributes', { defaultValue: {} }) attributes;
@attr('number', {
isNestedAttribute: true,
description: 'The default port a target should use if present.',
})
default_port;
/**
* @type {[FragmentHostSourceModel]}
+35 -1
View File
@@ -50,6 +50,12 @@ export default class ApplicationSerializer extends RESTSerializer {
// Do not serialize `disabled` fields.
// TODO: disabled is temporarily disabled
if (key === 'disabled') delete json[key];
// Push nested attributes down into the attributes key
if (options.isNestedAttribute && json[key] !== undefined) {
if (!json.attributes) json.attributes = {};
json.attributes[key] = json[key];
delete json[key];
}
return value;
}
@@ -195,9 +201,37 @@ export default class ApplicationSerializer extends RESTSerializer {
* @return {Object}
*/
normalize(typeClass, hash) {
const normalizedHash = copy(hash, true);
let normalizedHash = copy(hash, true);
const scopeID = get(normalizedHash, 'scope.id');
if (scopeID) normalizedHash.scope.scope_id = scopeID;
normalizedHash = this.normalizeNestedAttributes(typeClass, normalizedHash);
return super.normalize(typeClass, normalizedHash);
}
/**
* Certain typed resources in the API have type-specific fields nested under
* an `attributes` key in the payload
* (e.g. `attributes: { fieldName: '123' }`). Since Ember Data lacks
* first-class support for nested attributes, these fields must be hoisted up
* into the main body of the payload.
*
* In order to annotate a field as being a nested attribute, add the key name
* to the `nestedAttributes` field on the serializer:
* `@attr('string', { isNestedAttribute: true }) fieldName;`
*
* @param {Model} typeClass
* @param {Object} hash
* @return {Object}
*/
normalizeNestedAttributes(typeClass, hash) {
const normalizedHash = copy(hash, true);
typeClass.attributes.forEach((attribute) => {
const { isNestedAttribute } = attribute.options;
const attributeValue = normalizedHash.attributes?.[attribute.name];
if (isNestedAttribute && attributeValue) {
normalizedHash[attribute.name] = attributeValue;
}
});
return normalizedHash;
}
}
@@ -1 +0,0 @@
export { default } from 'api/models/fragment-target-attributes';
@@ -20,6 +20,7 @@ module('Unit | Serializer | target', function (hooks) {
scope_id: 'org_1',
type: 'org',
},
default_port: 1234,
version: 1,
type: 'tcp',
});
@@ -35,7 +36,7 @@ module('Unit | Serializer | target', function (hooks) {
session_max_seconds: 28800,
session_connection_limit: 1,
attributes: {
default_port: null,
default_port: 1234,
},
});
});
@@ -123,6 +124,40 @@ module('Unit | Serializer | target', function (hooks) {
});
});
test('it normalizes records with nested attributes', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
const serializer = store.serializerFor('target');
const targetModelClass = store.createRecord('target').constructor;
const payload = {
id: '1',
name: 'Target 1',
attributes: {
default_port: 1234,
},
};
const normalized = serializer.normalizeSingleResponse(
store,
targetModelClass,
payload
);
assert.deepEqual(normalized, {
included: [],
data: {
id: '1',
type: 'target',
attributes: {
application_credential_source_ids: [],
authorized_actions: [],
host_sources: [],
name: 'Target 1',
default_port: 1234,
},
relationships: {},
},
});
});
test('it normalizes missing host_sources and application_credential_source_ids to empty array', function (assert) {
assert.expect(1);
const store = this.owner.lookup('service:store');
+4 -2
View File
@@ -31,12 +31,12 @@
"dependencies": {
"ember-cli-babel": "^7.26.8",
"ember-cli-htmlbars": "^5.7.1",
"ember-composable-helpers": "^4.5.0",
"ember-focus-trap": "^0.7.0",
"ember-named-blocks-polyfill": "^0.2.4",
"ember-radio-button": "^2.0.1",
"ember-uuid": "^2.1.0",
"emberx-select": "github:adopted-ember-addons/emberx-select#bc5f774",
"ember-composable-helpers": "^4.5.0"
"emberx-select": "github:adopted-ember-addons/emberx-select#bc5f774"
},
"devDependencies": {
"@babel/core": "^7.16.5",
@@ -53,8 +53,10 @@
"@storybook/api": "^6.3.12",
"@storybook/cli": "^6.3.10",
"@storybook/components": "^6.3.12",
"@storybook/core-events": "^6.3.0",
"@storybook/ember": "^6.3.8",
"@storybook/ember-cli-storybook": "^0.4.0",
"@storybook/theming": "^6.3.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"broccoli-asset-rev": "^3.0.0",
@@ -94,7 +94,7 @@
<form.input
@name='default_port'
@type='number'
@value={{@model.attributes.default_port}}
@value={{@model.default_port}}
@label={{t 'form.default_port.label'}}
@error={{@model.errors.default_port}}
@helperText={{t 'form.default_port.help'}}
+48 -10
View File
@@ -4324,6 +4324,14 @@
core-js "^3.8.2"
global "^4.4.0"
"@storybook/client-logger@6.4.13":
version "6.4.13"
resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.4.13.tgz#2467ee13c7f85e9f6c0d9cd64c11ee7a109b060a"
integrity sha512-VPrrgJRURztXAKTeHOpzKMAHnNupkGApUDNlPIs0Qxyn5gaSiy806q4XPoROno3mVgEe+7Chf86hRiL8pJnlCA==
dependencies:
core-js "^3.8.2"
global "^4.4.0"
"@storybook/codemod@6.3.10":
version "6.3.10"
resolved "https://registry.yarnpkg.com/@storybook/codemod/-/codemod-6.3.10.tgz#aad0ee5ca8ef59b4d134ff45e213e198d64c9974"
@@ -4538,6 +4546,13 @@
dependencies:
core-js "^3.8.2"
"@storybook/core-events@^6.3.0":
version "6.4.13"
resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.4.13.tgz#caf1adafd743f8d53a151bc402449f841896cb9c"
integrity sha512-zNlzNv7qVXjLf7yfvY9KfLvDY8nVskxrjmz0+21rIqUefS9+7SWBrtJJURpCaoPf/BmACqh/6c1RnuOY7TESnw==
dependencies:
core-js "^3.8.2"
"@storybook/core-server@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.3.8.tgz#0d141e6f315b735a442aebc0f424f911456c769c"
@@ -4893,6 +4908,24 @@
resolve-from "^5.0.0"
ts-dedent "^2.0.0"
"@storybook/theming@^6.3.0":
version "6.4.13"
resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.4.13.tgz#1a8aadeddb6c3a115f739aa1a4bbd7e65d4a3830"
integrity sha512-oWRoNnvO4QnRnplZ74DVdU4k91eqw8y0Xqn6lzZBeC8hq6mYWldgfj1LZ24gJhVtEIa7ZKoyujGUygHaH8WXHw==
dependencies:
"@emotion/core" "^10.1.1"
"@emotion/is-prop-valid" "^0.8.6"
"@emotion/styled" "^10.0.27"
"@storybook/client-logger" "6.4.13"
core-js "^3.8.2"
deep-object-diff "^1.1.0"
emotion-theming "^10.0.27"
global "^4.4.0"
memoizerific "^1.11.3"
polished "^4.0.5"
resolve-from "^5.0.0"
ts-dedent "^2.0.0"
"@storybook/ui@6.3.8":
version "6.3.8"
resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.3.8.tgz#9fb71befbe76f06c478925610ce998c23260a3f3"
@@ -8141,9 +8174,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001157, caniuse-lite@^1.0.30001286:
version "1.0.30001295"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001295.tgz#68a60f8f0664f342b2835c5d8898b4faea7b3d51"
integrity sha512-lSP16vcyC0FEy0R4ECc9duSPoKoZy+YkpGkue9G4D81OfPnliopaZrU10+qtPdT8PbGXad/PNx43TIQrOmJZSQ==
version "1.0.30001300"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001300.tgz#11ab6c57d3eb6f964cba950401fd00a146786468"
integrity sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==
capture-exit@^2.0.0:
version "2.0.0"
@@ -13628,11 +13661,16 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.3, graceful-fs@^4.2.4:
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.3, graceful-fs@^4.2.4:
version "4.2.8"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
graceful-fs@^4.2.2:
version "4.2.9"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
growl@1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
@@ -14276,9 +14314,9 @@ ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8:
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
immer@8.0.1, immer@^9.0.6:
version "9.0.7"
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.7.tgz#b6156bd7db55db7abc73fd2fdadf4e579a701075"
integrity sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==
version "9.0.12"
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.12.tgz#2d33ddf3ee1d247deab9d707ca472c8c942a0f20"
integrity sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==
import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1:
version "3.3.0"
@@ -19133,9 +19171,9 @@ printf@^0.6.1:
integrity sha512-is0ctgGdPJ5951KulgfzvHGwJtZ5ck8l042vRkV6jrkpBzTmb/lueTqguWHy2JfVA+RY6gFVlaZgUS0j7S/dsw==
prismjs@^1.21.0, prismjs@^1.25.0, prismjs@~1.24.0:
version "1.25.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
version "1.26.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.26.0.tgz#16881b594828bb6b45296083a8cbab46b0accd47"
integrity sha512-HUoH9C5Z3jKkl3UunCyiD5jwk0+Hz0fIgQ2nbwU2Oo/ceuTAQAg+pPVnfdt2TJWRVLcxKh9iuoYDUSc8clb5UQ==
private@^0.1.8:
version "0.1.8"