flush out JT form; upgrade enzyme; add CheckboxField

This commit is contained in:
Keith Grant
2019-08-30 16:31:03 -07:00
parent 218348412b
commit e6475f21f6
8 changed files with 388 additions and 120 deletions

View File

@@ -2072,9 +2072,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "11.13.4", "version": "12.7.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.4.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.2.tgz",
"integrity": "sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ==", "integrity": "sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg==",
"dev": true "dev": true
}, },
"@types/stack-utils": { "@types/stack-utils": {
@@ -2338,13 +2338,13 @@
"integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg==" "integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg=="
}, },
"airbnb-prop-types": { "airbnb-prop-types": {
"version": "2.13.2", "version": "2.15.0",
"resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz", "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz",
"integrity": "sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ==", "integrity": "sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA==",
"dev": true, "dev": true,
"requires": { "requires": {
"array.prototype.find": "^2.0.4", "array.prototype.find": "^2.1.0",
"function.prototype.name": "^1.1.0", "function.prototype.name": "^1.1.1",
"has": "^1.0.3", "has": "^1.0.3",
"is-regex": "^1.0.4", "is-regex": "^1.0.4",
"object-is": "^1.0.1", "object-is": "^1.0.1",
@@ -2352,9 +2352,21 @@
"object.entries": "^1.1.0", "object.entries": "^1.1.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"prop-types-exact": "^1.2.0", "prop-types-exact": "^1.2.0",
"react-is": "^16.8.6" "react-is": "^16.9.0"
}, },
"dependencies": { "dependencies": {
"function.prototype.name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.1.tgz",
"integrity": "sha512-e1NzkiJuw6xqVH7YSdiW/qDHebcmMhPNe6w+4ZYYEg0VA+LaLzx37RimbPLuonHhYGFGPx1ME2nSi74JiaCr/Q==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"function-bind": "^1.1.1",
"functions-have-names": "^1.1.1",
"is-callable": "^1.1.4"
}
},
"object.entries": { "object.entries": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
@@ -2379,9 +2391,9 @@
} }
}, },
"react-is": { "react-is": {
"version": "16.8.6", "version": "16.9.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==",
"dev": true "dev": true
} }
} }
@@ -2949,13 +2961,35 @@
"dev": true "dev": true
}, },
"array.prototype.find": { "array.prototype.find": {
"version": "2.0.4", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.0.tgz",
"integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", "integrity": "sha512-Wn41+K1yuO5p7wRZDl7890c3xvv5UBrfVXTVIe28rSQb6LS0fZMDrQB6PAcxQFRFy6vJTLDc3A2+3CjQdzVKRg==",
"dev": true, "dev": true,
"requires": { "requires": {
"define-properties": "^1.1.2", "define-properties": "^1.1.3",
"es-abstract": "^1.7.0" "es-abstract": "^1.13.0"
},
"dependencies": {
"es-abstract": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.0",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"is-callable": "^1.1.4",
"is-regex": "^1.0.4",
"object-keys": "^1.0.12"
}
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
}
} }
}, },
"array.prototype.flat": { "array.prototype.flat": {
@@ -5183,7 +5217,7 @@
}, },
"css-select": { "css-select": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
"dev": true, "dev": true,
"requires": { "requires": {
@@ -5886,9 +5920,9 @@
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
}, },
"enzyme": { "enzyme": {
"version": "3.9.0", "version": "3.10.0",
"resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.9.0.tgz", "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.10.0.tgz",
"integrity": "sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==", "integrity": "sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg==",
"dev": true, "dev": true,
"requires": { "requires": {
"array.prototype.flat": "^1.2.1", "array.prototype.flat": "^1.2.1",
@@ -5915,18 +5949,19 @@
} }
}, },
"enzyme-adapter-react-16": { "enzyme-adapter-react-16": {
"version": "1.12.1", "version": "1.14.0",
"resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.12.1.tgz", "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.14.0.tgz",
"integrity": "sha512-GB61gvY97XvrA6qljExGY+lgI6BBwz+ASLaRKct9VQ3ozu0EraqcNn3CcrUckSGIqFGa1+CxO5gj5is5t3lwrw==", "integrity": "sha512-7PcOF7pb4hJUvjY7oAuPGpq3BmlCig3kxXGi2kFx0YzJHppqX1K8IIV9skT1IirxXlu8W7bneKi+oQ10QRnhcA==",
"dev": true, "dev": true,
"requires": { "requires": {
"enzyme-adapter-utils": "^1.11.0", "enzyme-adapter-utils": "^1.12.0",
"has": "^1.0.3",
"object.assign": "^4.1.0", "object.assign": "^4.1.0",
"object.values": "^1.1.0", "object.values": "^1.1.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react-is": "^16.8.6", "react-is": "^16.8.6",
"react-test-renderer": "^16.0.0-0", "react-test-renderer": "^16.0.0-0",
"semver": "^5.6.0" "semver": "^5.7.0"
}, },
"dependencies": { "dependencies": {
"prop-types": { "prop-types": {
@@ -5941,20 +5976,26 @@
} }
}, },
"react-is": { "react-is": {
"version": "16.8.6", "version": "16.9.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==",
"dev": true
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true "dev": true
} }
} }
}, },
"enzyme-adapter-utils": { "enzyme-adapter-utils": {
"version": "1.11.0", "version": "1.12.0",
"resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.11.0.tgz", "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.0.tgz",
"integrity": "sha512-0VZeoE9MNx+QjTfsjmO1Mo+lMfunucYB4wt5ficU85WB/LoetTJrbuujmHP3PJx6pSoaAuLA+Mq877x4LoxdNg==", "integrity": "sha512-wkZvE0VxcFx/8ZsBw0iAbk3gR1d9hK447ebnSYBf95+r32ezBq+XDSAvRErkc4LZosgH8J7et7H7/7CtUuQfBA==",
"dev": true, "dev": true,
"requires": { "requires": {
"airbnb-prop-types": "^2.12.0", "airbnb-prop-types": "^2.13.2",
"function.prototype.name": "^1.1.0", "function.prototype.name": "^1.1.0",
"object.assign": "^4.1.0", "object.assign": "^4.1.0",
"object.fromentries": "^2.0.0", "object.fromentries": "^2.0.0",
@@ -5974,9 +6015,9 @@
} }
}, },
"react-is": { "react-is": {
"version": "16.8.6", "version": "16.9.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==",
"dev": true "dev": true
} }
} }
@@ -7940,6 +7981,12 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true "dev": true
}, },
"functions-have-names": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.1.1.tgz",
"integrity": "sha512-U0kNHUoxwPNPWOJaMG7Z00d4a/qZVrFtzWJRaK8V9goaVOCXBSQSJpt3MYGNtkScKEBKovxLjnNdC9MlXwo5Pw==",
"dev": true
},
"fuzzaldrin": { "fuzzaldrin": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz", "resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz",
@@ -8348,9 +8395,9 @@
} }
}, },
"html-element-map": { "html-element-map": {
"version": "1.0.1", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.0.1.tgz", "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.1.0.tgz",
"integrity": "sha512-BZSfdEm6n706/lBfXKWa4frZRZcT5k1cOusw95ijZsHlI+GdgY0v95h6IzO3iIDf2ROwq570YTwqNPqHcNMozw==", "integrity": "sha512-iqiG3dTZmy+uUaTmHarTL+3/A2VW9ox/9uasKEZC+R/wAtUrTcRlXPSaPqsnWPfIu8wqn09jQNwMRqzL54jSYA==",
"dev": true, "dev": true,
"requires": { "requires": {
"array-filter": "^1.0.0" "array-filter": "^1.0.0"
@@ -8396,9 +8443,9 @@
}, },
"dependencies": { "dependencies": {
"readable-stream": { "readable-stream": {
"version": "3.3.0", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
"integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"inherits": "^2.0.3", "inherits": "^2.0.3",
@@ -8406,13 +8453,19 @@
"util-deprecate": "^1.0.1" "util-deprecate": "^1.0.1"
} }
}, },
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
"dev": true
},
"string_decoder": { "string_decoder": {
"version": "1.2.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dev": true, "dev": true,
"requires": { "requires": {
"safe-buffer": "~5.1.0" "safe-buffer": "~5.2.0"
} }
} }
} }
@@ -11809,9 +11862,9 @@
"dev": true "dev": true
}, },
"nearley": { "nearley": {
"version": "2.16.0", "version": "2.18.0",
"resolved": "https://registry.npmjs.org/nearley/-/nearley-2.16.0.tgz", "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.18.0.tgz",
"integrity": "sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==", "integrity": "sha512-/zQOMCeJcioI0xJtd5RpBiWw2WP7wLe6vq8/3Yu0rEwgus/G/+pViX80oA87JdVgjRt2895mZSv2VfZmy4W1uw==",
"dev": true, "dev": true,
"requires": { "requires": {
"commander": "^2.19.0", "commander": "^2.19.0",
@@ -13376,32 +13429,22 @@
} }
}, },
"react-test-renderer": { "react-test-renderer": {
"version": "16.8.6", "version": "16.9.0",
"resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz", "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.9.0.tgz",
"integrity": "sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==", "integrity": "sha512-R62stB73qZyhrJo7wmCW9jgl/07ai+YzvouvCXIJLBkRlRqLx4j9RqcLEAfNfU3OxTGucqR2Whmn3/Aad6L3hQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
"prop-types": "^15.6.2", "prop-types": "^15.6.2",
"react-is": "^16.8.6", "react-is": "^16.9.0",
"scheduler": "^0.13.6" "scheduler": "^0.15.0"
}, },
"dependencies": { "dependencies": {
"react-is": { "react-is": {
"version": "16.8.6", "version": "16.9.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
"integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==",
"dev": true "dev": true
},
"scheduler": {
"version": "0.13.6",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
"integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
}
} }
} }
}, },
@@ -14364,6 +14407,16 @@
"object-assign": "^4.1.1" "object-assign": "^4.1.1"
} }
}, },
"scheduler": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz",
"integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
}
},
"schema-utils": { "schema-utils": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@@ -15250,14 +15303,36 @@
} }
}, },
"string.prototype.trim": { "string.prototype.trim": {
"version": "1.1.2", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.0.tgz",
"integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", "integrity": "sha512-9EIjYD/WdlvLpn987+ctkLf0FfvBefOCuiEr2henD8X+7jfwPnyvTdmW8OJhj5p+M0/96mBdynLWkxUr+rHlpg==",
"dev": true, "dev": true,
"requires": { "requires": {
"define-properties": "^1.1.2", "define-properties": "^1.1.3",
"es-abstract": "^1.5.0", "es-abstract": "^1.13.0",
"function-bind": "^1.0.2" "function-bind": "^1.1.1"
},
"dependencies": {
"es-abstract": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
"dev": true,
"requires": {
"es-to-primitive": "^1.2.0",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"is-callable": "^1.1.4",
"is-regex": "^1.0.4",
"object-keys": "^1.0.12"
}
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
}
} }
}, },
"string_decoder": { "string_decoder": {

View File

@@ -33,8 +33,8 @@
"babel-plugin-macros": "^2.4.2", "babel-plugin-macros": "^2.4.2",
"babel-plugin-styled-components": "^1.10.0", "babel-plugin-styled-components": "^1.10.0",
"css-loader": "^1.0.0", "css-loader": "^1.0.0",
"enzyme": "^3.9.0", "enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.12.1", "enzyme-adapter-react-16": "^1.14.0",
"enzyme-to-json": "^3.3.5", "enzyme-to-json": "^3.3.5",
"eslint": "^5.6.0", "eslint": "^5.6.0",
"eslint-config-airbnb": "^17.1.0", "eslint-config-airbnb": "^17.1.0",

View File

@@ -1,5 +1,13 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import {
arrayOf,
oneOfType,
func,
number,
string,
shape,
bool,
} from 'prop-types';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { FormSelect, FormSelectOption } from '@patternfly/react-core'; import { FormSelect, FormSelectOption } from '@patternfly/react-core';
@@ -48,12 +56,12 @@ AnsibleSelect.defaultProps = {
}; };
AnsibleSelect.propTypes = { AnsibleSelect.propTypes = {
data: PropTypes.arrayOf(PropTypes.object), data: arrayOf(shape()),
id: PropTypes.string.isRequired, id: string.isRequired,
isValid: PropTypes.bool, isValid: bool,
onBlur: PropTypes.func, onBlur: func,
onChange: PropTypes.func.isRequired, onChange: func.isRequired,
value: PropTypes.string.isRequired, value: oneOfType([string, number]).isRequired,
}; };
export { AnsibleSelect as _AnsibleSelect }; export { AnsibleSelect as _AnsibleSelect };

View File

@@ -0,0 +1,54 @@
import React from 'react';
import { string, func } from 'prop-types';
import { Field } from 'formik';
import { Checkbox, Tooltip } from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
import styled from 'styled-components';
const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px;
`;
function CheckboxField({ id, name, label, tooltip, validate, ...rest }) {
return (
<Field
name={name}
validate={validate}
render={({ field }) => (
<Checkbox
label={
<span>
{label}
&nbsp;
{tooltip && (
<Tooltip position="right" content={tooltip}>
<QuestionCircleIcon />
</Tooltip>
)}
</span>
}
id={id}
{...rest}
checked={field.value}
{...field}
onChange={(value, event) => {
field.onChange(event);
}}
/>
)}
/>
);
}
CheckboxField.propTypes = {
id: string.isRequired,
name: string.isRequired,
label: string.isRequired,
validate: func,
tooltip: string,
};
CheckboxField.defaultProps = {
validate: () => {},
tooltip: '',
};
export default CheckboxField;

View File

@@ -1 +1,2 @@
export { default } from './FormField'; export { default } from './FormField';
export { default as CheckboxField } from './CheckboxField';

View File

@@ -7,12 +7,16 @@ function arrayToString(tags) {
} }
function stringToArray(value) { function stringToArray(value) {
return value.split(',').map(v => ({ return value.split(',').filter(val => !!val).map(val => ({
id: v, id: val,
name: v, name: val,
})); }));
} }
/*
* Adapter providing a simplified API to a MultiSelect. The value
* is a comma-separated string.
*/
function TagMultiSelect ({ onChange, value }) { function TagMultiSelect ({ onChange, value }) {
const [options, setOptions] = useState(stringToArray(value)); const [options, setOptions] = useState(stringToArray(value));

View File

@@ -0,0 +1,34 @@
import React from 'react';
import { mount } from 'enzyme';
import TagMultiSelect from './TagMultiSelect';
describe('<TagMultiSelect />', () => {
it('should render MultiSelect', () => {
const wrapper = mount(
<TagMultiSelect value="foo,bar" onChange={jest.fn()} />
);
expect(wrapper.find('MultiSelect').prop('options')).toEqual([
{ id: 'foo', name: 'foo' },
{ id: 'bar', name: 'bar' },
]);
});
it('should not treat empty string as an option', () => {
const wrapper = mount(<TagMultiSelect value="" onChange={jest.fn()} />);
expect(wrapper.find('MultiSelect').prop('options')).toEqual([]);
});
// NOTE: this test throws a warning which *should* be go away once we upgrade
// to React 16.8 (https://github.com/airbnb/enzyme/blob/master/docs/api/ReactWrapper/invoke.md)
it('should trigger onChange', () => {
const onChange = jest.fn();
const wrapper = mount(
<TagMultiSelect value="foo,bar" onChange={onChange} />
);
const input = wrapper.find('TextInput');
input.invoke('onChange')('baz');
input.invoke('onKeyDown')({ key: 'Tab' });
expect(onChange).toHaveBeenCalledWith('foo,bar,baz');
});
});

View File

@@ -4,14 +4,21 @@ import { withRouter } from 'react-router-dom';
import { withI18n } from '@lingui/react'; import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { withFormik, Field } from 'formik'; import { withFormik, Field } from 'formik';
import { Form, FormGroup, Tooltip, Card, Switch } from '@patternfly/react-core'; import {
Form,
FormGroup,
Tooltip,
Card,
Switch,
Checkbox,
} from '@patternfly/react-core';
import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons'; import { QuestionCircleIcon as PFQuestionCircleIcon } from '@patternfly/react-icons';
import ContentError from '@components/ContentError'; import ContentError from '@components/ContentError';
import ContentLoading from '@components/ContentLoading'; import ContentLoading from '@components/ContentLoading';
import AnsibleSelect from '@components/AnsibleSelect'; import AnsibleSelect from '@components/AnsibleSelect';
import MultiSelect, { TagMultiSelect } from '@components/MultiSelect'; import MultiSelect, { TagMultiSelect } from '@components/MultiSelect';
import FormActionGroup from '@components/FormActionGroup'; import FormActionGroup from '@components/FormActionGroup';
import FormField from '@components/FormField'; import FormField, { CheckboxField } from '@components/FormField';
import FormRow from '@components/FormRow'; import FormRow from '@components/FormRow';
import CollapsibleSection from '@components/CollapsibleSection'; import CollapsibleSection from '@components/CollapsibleSection';
import { required } from '@util/validators'; import { required } from '@util/validators';
@@ -25,6 +32,17 @@ const QuestionCircleIcon = styled(PFQuestionCircleIcon)`
margin-left: 10px; margin-left: 10px;
`; `;
const GridFormGroup = styled(FormGroup)`
& > label {
grid-column: 1 / -1;
}
&& {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}
`;
class JobTemplateForm extends Component { class JobTemplateForm extends Component {
static propTypes = { static propTypes = {
template: JobTemplate, template: JobTemplate,
@@ -60,6 +78,7 @@ class JobTemplateForm extends Component {
inventory: props.template.summary_fields.inventory, inventory: props.template.summary_fields.inventory,
relatedProjectPlaybooks: props.relatedProjectPlaybooks, relatedProjectPlaybooks: props.relatedProjectPlaybooks,
relatedInstanceGroups: [], relatedInstanceGroups: [],
allowCallbacks: !!props.template.host_config_key,
}; };
this.handleNewLabel = this.handleNewLabel.bind(this); this.handleNewLabel = this.handleNewLabel.bind(this);
this.loadLabels = this.loadLabels.bind(this); this.loadLabels = this.loadLabels.bind(this);
@@ -119,9 +138,10 @@ class JobTemplateForm extends Component {
return; return;
} }
try { try {
console.log('loading...');
const { data } = await JobTemplatesAPI.readInstanceGroups(template.id); const { data } = await JobTemplatesAPI.readInstanceGroups(template.id);
console.log(data.results); this.setState({
relatedInstanceGroups: data.results,
});
} catch (err) { } catch (err) {
this.setState({ contentError: err }); this.setState({ contentError: err });
} }
@@ -236,6 +256,7 @@ class JobTemplateForm extends Component {
newLabels, newLabels,
removedLabels, removedLabels,
relatedInstanceGroups, relatedInstanceGroups,
allowCallbacks,
} = this.state; } = this.state;
const { const {
handleCancel, handleCancel,
@@ -554,47 +575,110 @@ class JobTemplateForm extends Component {
/> />
<Field <Field
name="job_tags" name="job_tags"
render={({ field, form }) => { render={({ field, form }) => (
return ( <FormGroup
<FormGroup label={i18n._(t`Job Tags`)}
label={i18n._(t`Job Tags`)} fieldId="template-job-tags"
fieldId="template-job-tags" >
> <Tooltip
<Tooltip position="right"
position="right" content={i18n._(t`Tags are useful when you have a large
content={i18n._(t`Tags are useful when you have a large
playbook, and you want to run a specific part of a playbook, and you want to run a specific part of a
play or task. Use commas to separate multiple tags. play or task. Use commas to separate multiple tags.
Refer to Ansible Tower documentation for details on Refer to Ansible Tower documentation for details on
the usage of tags.`)} the usage of tags.`)}
> >
<QuestionCircleIcon /> <QuestionCircleIcon />
</Tooltip> </Tooltip>
<TagMultiSelect <TagMultiSelect
onChange={value => form.setFieldValue(field.name, value)} value={field.value}
value={field.value} onChange={value => form.setFieldValue(field.name, value)}
/> />
</FormGroup> </FormGroup>
); )}
}}
/> />
<FormGroup label={i18n._(t`Skip Tags`)} fieldId="template-skip-tags"> <Field
<Tooltip name="skip_tags"
position="right" render={({ field, form }) => (
content={i18n._(t`Skip tags are useful when you have a <FormGroup
label={i18n._(t`Skip Tags`)}
fieldId="template-skip-tags"
>
<Tooltip
position="right"
content={i18n._(t`Skip tags are useful when you have a
large playbook, and you want to skip specific parts of a large playbook, and you want to skip specific parts of a
play or task. Use commas to separate multiple tags. Refer play or task. Use commas to separate multiple tags. Refer
to Ansible Tower documentation for details on the usage to Ansible Tower documentation for details on the usage
of tags.`)} of tags.`)}
> >
<QuestionCircleIcon /> <QuestionCircleIcon />
</Tooltip> </Tooltip>
<MultiSelect <TagMultiSelect
onAddNewItem={this.handleNewLabel} value={field.value}
onRemoveItem={this.removeLabel} onChange={value => form.setFieldValue(field.name, value)}
associatedItems={template.skip_tags.split(',')} />
options={loadedLabels} </FormGroup>
)}
/>
<GridFormGroup isInline label={i18n._(t`Options`)}>
<CheckboxField
id="option-privilege-escalation"
name="become_enabled"
label={i18n._(t`Privilege Escalation`)}
tooltip={i18n._(
t`If enabled, run this playbook as an administrator.`
)}
/> />
<Checkbox
aria-label={i18n._(t`Provisioning Callbacks`)}
label={
<span>
{i18n._(t`Provisioning Callbacks`)}
&nbsp;
<Tooltip
position="right"
content={i18n._(
t`Enables creation of a provisioning callback URL. Using
the URL a host can contact {{BRAND_NAME}} and request a
configuration update using this job template.`
)}
>
<QuestionCircleIcon />
</Tooltip>
</span>
}
id="option-callbacks"
checked={allowCallbacks}
onChange={checked => {
this.setState({ allowCallbacks: checked });
}}
/>
<CheckboxField
id="option-concurrent"
name="allow_simultaneous"
label={i18n._(t`Concurrent Jobs`)}
tooltip={i18n._(
t`If enabled, simultaneous runs of this job template will
be allowed.`
)}
/>
<CheckboxField
id="option-fact-cache"
name="use_fact_cache"
label={i18n._(t`Fact Cache`)}
tooltip={i18n._(
t`If enabled, use cached facts if available and store
discovered facts in the cache.`
)}
/>
</GridFormGroup>
<FormGroup
css={`
${allowCallbacks ? '' : 'display: none'}
`}
>
HERE
</FormGroup> </FormGroup>
</CollapsibleSection> </CollapsibleSection>
<FormActionGroup onCancel={handleCancel} onSubmit={handleSubmit} /> <FormActionGroup onCancel={handleCancel} onSubmit={handleSubmit} />
@@ -621,6 +705,10 @@ const FormikApp = withFormik({
diff_mode, diff_mode,
job_tags, job_tags,
skip_tags, skip_tags,
become_enabled,
allow_callbacks,
allow_simultaneous,
use_fact_cache,
summary_fields = { labels: { results: [] } }, summary_fields = { labels: { results: [] } },
} = { ...template }; } = { ...template };
@@ -640,6 +728,10 @@ const FormikApp = withFormik({
diff_mode: diff_mode || false, diff_mode: diff_mode || false,
job_tags: job_tags || '', job_tags: job_tags || '',
skip_tags: skip_tags || '', skip_tags: skip_tags || '',
become_enabled: become_enabled || false,
allow_callbacks: allow_callbacks || false,
allow_simultaneous: allow_simultaneous || false,
use_fact_cache: use_fact_cache || false,
}; };
}, },
handleSubmit: (values, bag) => bag.props.handleSubmit(values), handleSubmit: (values, bag) => bag.props.handleSubmit(values),