From 946234d70872f94db260aeba2e2e3774b429dd16 Mon Sep 17 00:00:00 2001 From: Richard Vsiansky Date: Fri, 1 Mar 2019 16:24:16 +0100 Subject: [PATCH 1/4] Update typescript to latest and allow synthetic default exports --- package.json | 2 +- tsconfig.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b2d125f25ba..798788fa60a 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "stylelint": "^8.2.0", "stylelint-config-standard": "^17.0.0", "ts-jest": "~22.4.3", - "typescript": "~2.8.1", + "typescript": "~3.3.3333", "webpack": "~4.12.0", "webpack-cli": "~3.0.7", "webpack-dev-server": "~3.1.4", diff --git a/tsconfig.json b/tsconfig.json index 079c7232ded..e3a42046cf6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,8 @@ "app/javascript/typings" ], "allowJs": true, - "jsx": "react" + "jsx": "react", + "allowSyntheticDefaultImports": true, }, "exclude": [ "**/*.spec.ts", From 3859fe1307d1b995856749b4466fae3f18bed77f Mon Sep 17 00:00:00 2001 From: Richard Vsiansky Date: Wed, 27 Feb 2019 10:32:12 +0100 Subject: [PATCH 2/4] Adds library for debouncing promises --- app/javascript/helpers/promise-debounce.js | 7 +++++++ package.json | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 app/javascript/helpers/promise-debounce.js diff --git a/app/javascript/helpers/promise-debounce.js b/app/javascript/helpers/promise-debounce.js new file mode 100644 index 00000000000..ba9c49a8f5b --- /dev/null +++ b/app/javascript/helpers/promise-debounce.js @@ -0,0 +1,7 @@ +import AwesomeDebouncePromise from 'awesome-debounce-promise'; + +export default (asyncFunction, debounceTime = 250, options = undefined) => AwesomeDebouncePromise( + asyncFunction, + debounceTime, + options, +); diff --git a/package.json b/package.json index 798788fa60a..3ae9e817bea 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "homepage": "https://github.com/ManageIQ/manageiq#readme", "dependencies": { "@data-driven-forms/pf3-component-mapper": "^0.4.3", - "@data-driven-forms/react-form-renderer": "^1.7.0", + "@data-driven-forms/react-form-renderer": "^1.8.0", "@manageiq/react-ui-components": "~0.10.8", "@manageiq/ui-components": "~1.2.2", "@pf3/select": "~1.12.6", @@ -39,6 +39,7 @@ "angular-ui-sortable": "~0.16.1", "angular.validators": "~4.4.3", "array-includes": "~3.0.3", + "awesome-debounce-promise": "^2.1.0", "bootstrap-filestyle": "~1.2.1", "bootstrap-switch": "~3.3.4", "classnames": "~2.2.6", From efd1243fd09e5b9b62562afe950841898fe9a697 Mon Sep 17 00:00:00 2001 From: Richard Vsiansky Date: Thu, 7 Mar 2019 13:19:25 +0100 Subject: [PATCH 3/4] Updates data-driven-forms dependencies --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3ae9e817bea..19d10568dbf 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,8 @@ }, "homepage": "https://github.com/ManageIQ/manageiq#readme", "dependencies": { - "@data-driven-forms/pf3-component-mapper": "^0.4.3", - "@data-driven-forms/react-form-renderer": "^1.8.0", + "@data-driven-forms/pf3-component-mapper": "^0.4.5", + "@data-driven-forms/react-form-renderer": "^1.9.3", "@manageiq/react-ui-components": "~0.10.8", "@manageiq/ui-components": "~1.2.2", "@pf3/select": "~1.12.6", From 60dd4eb8a8e7688719d9e0370eade29fcc8c2d5b Mon Sep 17 00:00:00 2001 From: Richard Vsiansky Date: Wed, 27 Feb 2019 10:32:40 +0100 Subject: [PATCH 4/4] Adds async validator to catalog form --- .../catalog-form/catalog-form.schema.js | 24 ++++++++++--- .../__snapshots__/catalog-form.spec.js.snap | 10 ++---- .../spec/catalog-form/validator.spec.js | 35 +++++++++++++++++++ 3 files changed, 56 insertions(+), 13 deletions(-) create mode 100644 app/javascript/spec/catalog-form/validator.spec.js diff --git a/app/javascript/components/catalog-form/catalog-form.schema.js b/app/javascript/components/catalog-form/catalog-form.schema.js index e661d70ad9b..80cc9e48d26 100644 --- a/app/javascript/components/catalog-form/catalog-form.schema.js +++ b/app/javascript/components/catalog-form/catalog-form.schema.js @@ -1,4 +1,19 @@ -import { componentTypes, validatorTypes } from '@data-driven-forms/react-form-renderer'; +import { componentTypes } from '@data-driven-forms/react-form-renderer'; +import debouncePromise from '../../helpers/promise-debounce'; +import { API } from '../../http_api'; + +export const asyncValidator = value => API.get(`/api/service_catalogs?expand=resources&filter[]=name=${value}`) + .then((json) => { + if (json.resources.length > 0) { + return __('Name has already been taken'); + } + if (value === '' || value === undefined) { + return __("Name can't be blank"); + } + return undefined; + }); + +const asyncValidatorDebounced = debouncePromise(asyncValidator); function createSchema(options) { const fields = [{ @@ -7,10 +22,9 @@ function createSchema(options) { fields: [{ component: componentTypes.TEXT_FIELD, name: 'name', - validate: [{ - type: validatorTypes.REQUIRED, - message: __("Name can't be blank"), - }], + validate: [ + asyncValidatorDebounced, + ], label: __('Name'), maxLength: 40, autoFocus: true, diff --git a/app/javascript/spec/catalog-form/__snapshots__/catalog-form.spec.js.snap b/app/javascript/spec/catalog-form/__snapshots__/catalog-form.spec.js.snap index 06f9b10a487..96301984eac 100644 --- a/app/javascript/spec/catalog-form/__snapshots__/catalog-form.spec.js.snap +++ b/app/javascript/spec/catalog-form/__snapshots__/catalog-form.spec.js.snap @@ -27,10 +27,7 @@ exports[`Catalog form component should render add variant form 1`] = ` "maxLength": 40, "name": "name", "validate": Array [ - Object { - "message": "Name can't be blank", - "type": "required-validator", - }, + [Function], ], "validateOnMount": true, }, @@ -120,10 +117,7 @@ exports[`Catalog form component should render edit variant form 1`] = ` "maxLength": 40, "name": "name", "validate": Array [ - Object { - "message": "Name can't be blank", - "type": "required-validator", - }, + [Function], ], "validateOnMount": true, }, diff --git a/app/javascript/spec/catalog-form/validator.spec.js b/app/javascript/spec/catalog-form/validator.spec.js new file mode 100644 index 00000000000..c3b3bcbfbb2 --- /dev/null +++ b/app/javascript/spec/catalog-form/validator.spec.js @@ -0,0 +1,35 @@ +import fetchMock from 'fetch-mock'; +import { asyncValidator } from '../../components/catalog-form/catalog-form.schema'; + +describe('catalog form - promise validator', () => { + afterEach(() => { + fetchMock.reset(); + fetchMock.restore(); + }); + + it('returns error message when name is taken', () => { + fetchMock.getOnce('/api/service_catalogs?expand=resources&filter[]=name=a1', { + resources: [ + { name: 'a1' }, + ], + }); + + return asyncValidator('a1').then(data => expect(data).toEqual(__('Name has already been taken'))); + }); + + it('returns error message when name is undefined', () => { + fetchMock.getOnce('/api/service_catalogs?expand=resources&filter[]=name=undefined', { + resources: [], + }); + + return asyncValidator(undefined).then(data => expect(data).toEqual(__("Name can't be blank"))); + }); + + it('returns nothing when passes', () => { + fetchMock.getOnce('/api/service_catalogs?expand=resources&filter[]=name=a1', { + resources: [], + }); + + return asyncValidator('a1').then(data => expect(data).toEqual(undefined)); + }); +});