mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
Merge pull request #7305 from jlmitch5/pfv4upgrade
patternfly v4 upgrade Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
commit
a669db989c
389
awx/ui_next/package-lock.json
generated
389
awx/ui_next/package-lock.json
generated
@ -1150,31 +1150,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz",
|
||||
"integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg=="
|
||||
},
|
||||
"@emotion/babel-utils": {
|
||||
"version": "0.6.10",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-utils/-/babel-utils-0.6.10.tgz",
|
||||
"integrity": "sha512-/fnkM/LTEp3jKe++T0KyTszVGWNKPNOUJfjNKLO17BzQ6QPxgbg3whayom1Qr2oLFH3V92tDymU+dT5q676uow==",
|
||||
"requires": {
|
||||
"@emotion/hash": "^0.6.6",
|
||||
"@emotion/memoize": "^0.6.6",
|
||||
"@emotion/serialize": "^0.9.1",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"find-root": "^1.1.0",
|
||||
"source-map": "^0.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
|
||||
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@emotion/hash": {
|
||||
"version": "0.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.6.tgz",
|
||||
"integrity": "sha512-ojhgxzUHZ7am3D2jHkMzPpsBAiB005GF5YU4ea+8DNPybMk01JJUM9V9YRlF/GE95tcOm8DxQvWA2jq19bGalQ=="
|
||||
},
|
||||
"@emotion/is-prop-valid": {
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||
@ -1190,50 +1165,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@emotion/memoize": {
|
||||
"version": "0.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.6.6.tgz",
|
||||
"integrity": "sha512-h4t4jFjtm1YV7UirAFuSuFGyLa+NNxjdkq6DpFLANNQY5rHueFZHVY+8Cu1HYVP6DrheB0kv4m5xPjo7eKT7yQ=="
|
||||
},
|
||||
"@emotion/serialize": {
|
||||
"version": "0.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.9.1.tgz",
|
||||
"integrity": "sha512-zTuAFtyPvCctHBEL8KZ5lJuwBanGSutFEncqLn/m9T1a6a93smBStK+bZzcNPgj4QS8Rkw9VTwJGhRIUVO8zsQ==",
|
||||
"requires": {
|
||||
"@emotion/hash": "^0.6.6",
|
||||
"@emotion/memoize": "^0.6.6",
|
||||
"@emotion/unitless": "^0.6.7",
|
||||
"@emotion/utils": "^0.8.2"
|
||||
}
|
||||
},
|
||||
"@emotion/stylis": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.7.1.tgz",
|
||||
"integrity": "sha512-/SLmSIkN13M//53TtNxgxo57mcJk/UJIDFRKwOiLIBEyBHEcipgR6hNMQ/59Sl4VjCJ0Z/3zeAZyvnSLPG/1HQ=="
|
||||
},
|
||||
"@emotion/unitless": {
|
||||
"version": "0.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.6.7.tgz",
|
||||
"integrity": "sha512-Arj1hncvEVqQ2p7Ega08uHLr1JuRYBuO5cIvcA+WWEQ5+VmkOE3ZXzl04NbQxeQpWX78G7u6MqxKuNX3wvYZxg=="
|
||||
},
|
||||
"@emotion/utils": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz",
|
||||
"integrity": "sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw=="
|
||||
},
|
||||
"@fortawesome/fontawesome-common-types": {
|
||||
"version": "0.2.28",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.28.tgz",
|
||||
"integrity": "sha512-gtis2/5yLdfI6n0ia0jH7NJs5i/Z/8M/ZbQL6jXQhCthEOe5Cr5NcQPhgTvFxNOtURE03/ZqUcEskdn2M+QaBg=="
|
||||
},
|
||||
"@fortawesome/free-brands-svg-icons": {
|
||||
"version": "5.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.13.0.tgz",
|
||||
"integrity": "sha512-/6xXiJFCMEQxqxXbL0FPJpwq5Cv6MRrjsbJEmH/t5vOvB4dILDpnY0f7zZSlA8+TG7jwlt12miF/yZpZkykucA==",
|
||||
"requires": {
|
||||
"@fortawesome/fontawesome-common-types": "^0.2.28"
|
||||
}
|
||||
},
|
||||
"@hapi/address": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
|
||||
@ -1704,62 +1635,45 @@
|
||||
"dev": true
|
||||
},
|
||||
"@patternfly/patternfly": {
|
||||
"version": "2.71.6",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-2.71.6.tgz",
|
||||
"integrity": "sha512-mqqtuCVa+/FbyyK8hSAcfEIwNX73+zbnzHpmC4NrW0kyMzSszPtBqev/ZO79ZxGqZUpLOyUBTVaH7oKn8cL35Q=="
|
||||
"version": "4.10.31",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-4.10.31.tgz",
|
||||
"integrity": "sha512-UxdZ/apWRowXYZ5qPz5LPfXwyB4YGpomrCJPX7c36+Zg8jFpYyVqgVYainL8Yf/GrChtC2LKyoHg7UUTtMtp4A=="
|
||||
},
|
||||
"@patternfly/react-core": {
|
||||
"version": "3.158.1",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-3.158.1.tgz",
|
||||
"integrity": "sha512-LUknvaIBoo0ftu7OBZhyGn7Cu3IfhaO4nXx17M99OYc76yKBv1jJMmTTUh7OX3QyWH961gH1K7Z3GlJV7v57ZA==",
|
||||
"version": "4.18.14",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-4.18.14.tgz",
|
||||
"integrity": "sha512-aFOBX02ud78eCu7rtbUTr+Rj/J7BertxDssSWFb+uDQrUN268dSH9/tvHcDd3//YZrsCoBbky9ngRa4Jt1fryg==",
|
||||
"requires": {
|
||||
"@patternfly/react-icons": "^3.15.17",
|
||||
"@patternfly/react-styles": "^3.7.14",
|
||||
"@patternfly/react-tokens": "^2.8.14",
|
||||
"@patternfly/react-icons": "^4.3.6",
|
||||
"@patternfly/react-styles": "^4.3.6",
|
||||
"@patternfly/react-tokens": "^4.4.5",
|
||||
"focus-trap": "4.0.2",
|
||||
"react-dropzone": "9.0.0",
|
||||
"tippy.js": "5.1.2"
|
||||
"tippy.js": "5.1.2",
|
||||
"tslib": "^1.11.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@patternfly/react-icons": {
|
||||
"version": "3.15.17",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-3.15.17.tgz",
|
||||
"integrity": "sha512-Q0JAlxEvSAl5kcMSUMItLiKi9fweO941g5+lS45t3o/Rv4Eg91Ig7AyK1YWw6m1ah+/eHslLfox0Uqw7m7usLg==",
|
||||
"requires": {
|
||||
"@fortawesome/free-brands-svg-icons": "^5.8.1"
|
||||
}
|
||||
},
|
||||
"@patternfly/react-tokens": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-2.8.14.tgz",
|
||||
"integrity": "sha512-pha0XyZ3ZiXuQoKstuFsiEHARFQKUFsS6WxVuRSEyNbGTToRNJkKR9cW5swzHgXK6Fuw5EA2XFHLuu8osj52KA=="
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.4.0.tgz",
|
||||
"integrity": "sha512-UKQI5luZ6Bd3SLljl4WNFVhtteUiM2lbKz5qjgBZn3zLOW2Zigv6M1zkgII6rMW9Rxql/UEDZkvNmilf84HW+g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@patternfly/react-icons": {
|
||||
"version": "3.15.17",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-3.15.17.tgz",
|
||||
"integrity": "sha512-Q0JAlxEvSAl5kcMSUMItLiKi9fweO941g5+lS45t3o/Rv4Eg91Ig7AyK1YWw6m1ah+/eHslLfox0Uqw7m7usLg==",
|
||||
"requires": {
|
||||
"@fortawesome/free-brands-svg-icons": "^5.8.1"
|
||||
}
|
||||
"version": "4.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-4.3.5.tgz",
|
||||
"integrity": "sha512-+GublxpFXR+y/5zygf9q00/LvIvso8jr0mxZGhVxsKmi2dUu7xAvN+T+5vjS9fiMbXf7WXsSPXST/UTiBIVTdQ=="
|
||||
},
|
||||
"@patternfly/react-styles": {
|
||||
"version": "3.7.14",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-3.7.14.tgz",
|
||||
"integrity": "sha512-NVwbPP9JroulfQgj0LOLWKP4DumArW8RrP1FB1lLOCuw13KkuAcFbLN9MSF8ZBwJ8syxGEdux5mDC3jPjsrQiw==",
|
||||
"requires": {
|
||||
"camel-case": "^3.0.0",
|
||||
"css": "^2.2.3",
|
||||
"cssstyle": "^0.3.1",
|
||||
"emotion": "^9.2.9",
|
||||
"emotion-server": "^9.2.9"
|
||||
}
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-4.4.0.tgz",
|
||||
"integrity": "sha512-0guVqVVvLgDMKAqLM9Vb3T9sjSPBGm9DzTURuZrIz/gx9gKuckSA42OS1aTTtZLXz6ryYoOn7uQJiIhaJu1F0Q=="
|
||||
},
|
||||
"@patternfly/react-tokens": {
|
||||
"version": "2.8.14",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-2.8.14.tgz",
|
||||
"integrity": "sha512-pha0XyZ3ZiXuQoKstuFsiEHARFQKUFsS6WxVuRSEyNbGTToRNJkKR9cW5swzHgXK6Fuw5EA2XFHLuu8osj52KA=="
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-4.5.0.tgz",
|
||||
"integrity": "sha512-cfxWduAIIFuRnuTuTkColGCoGPmdXy2ousabpGd+Yi3vbwWcWYIRlrLuetK1VMmddnt2PW9PnaLDW6bH3+oagQ=="
|
||||
},
|
||||
"@sheerun/mutationobserver-shim": {
|
||||
"version": "0.3.3",
|
||||
@ -2565,11 +2479,6 @@
|
||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz",
|
||||
"integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg=="
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
@ -3180,32 +3089,6 @@
|
||||
"object.assign": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"babel-plugin-emotion": {
|
||||
"version": "9.2.11",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-9.2.11.tgz",
|
||||
"integrity": "sha512-dgCImifnOPPSeXod2znAmgc64NhaaOjGEHROR/M+lmStb3841yK1sgaDYAYMnlvWNz8GnpwIPN0VmNpbWYZ+VQ==",
|
||||
"requires": {
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"@emotion/babel-utils": "^0.6.4",
|
||||
"@emotion/hash": "^0.6.2",
|
||||
"@emotion/memoize": "^0.6.1",
|
||||
"@emotion/stylis": "^0.7.0",
|
||||
"babel-plugin-macros": "^2.0.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"convert-source-map": "^1.5.0",
|
||||
"find-root": "^1.1.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"source-map": "^0.5.7",
|
||||
"touch": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-plugin-istanbul": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz",
|
||||
@ -3293,7 +3176,7 @@
|
||||
},
|
||||
"babel-plugin-syntax-jsx": {
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
|
||||
"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
|
||||
},
|
||||
"babel-plugin-syntax-object-rest-spread": {
|
||||
@ -3735,7 +3618,7 @@
|
||||
},
|
||||
"browserify-aes": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
|
||||
"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
|
||||
"requires": {
|
||||
"buffer-xor": "^1.0.3",
|
||||
@ -3769,7 +3652,7 @@
|
||||
},
|
||||
"browserify-rsa": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
||||
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
||||
"requires": {
|
||||
"bn.js": "^4.1.0",
|
||||
@ -3867,11 +3750,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
|
||||
"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
|
||||
},
|
||||
"buffer-indexof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
|
||||
@ -3976,15 +3854,6 @@
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
|
||||
},
|
||||
"camel-case": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
|
||||
"integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
|
||||
"requires": {
|
||||
"no-case": "^2.2.0",
|
||||
"upper-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
@ -4633,33 +4502,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"create-emotion": {
|
||||
"version": "9.2.12",
|
||||
"resolved": "https://registry.npmjs.org/create-emotion/-/create-emotion-9.2.12.tgz",
|
||||
"integrity": "sha512-P57uOF9NL2y98Xrbl2OuiDQUZ30GVmASsv5fbsjF4Hlraip2kyAvMm+2PoYUvFFw03Fhgtxk3RqZSm2/qHL9hA==",
|
||||
"requires": {
|
||||
"@emotion/hash": "^0.6.2",
|
||||
"@emotion/memoize": "^0.6.1",
|
||||
"@emotion/stylis": "^0.7.0",
|
||||
"@emotion/unitless": "^0.6.2",
|
||||
"csstype": "^2.5.2",
|
||||
"stylis": "^3.5.0",
|
||||
"stylis-rule-sheet": "^0.0.10"
|
||||
}
|
||||
},
|
||||
"create-emotion-server": {
|
||||
"version": "9.2.12",
|
||||
"resolved": "https://registry.npmjs.org/create-emotion-server/-/create-emotion-server-9.2.12.tgz",
|
||||
"integrity": "sha512-ET+E6A5MkQTEBNDYAnjh6+0cB33qStFXhtflkZNPEaOmvzYlB/xcPnpUk4J7ul3MVa8PCQx2Ei5g2MGY/y1n+g==",
|
||||
"requires": {
|
||||
"html-tokenize": "^2.0.0",
|
||||
"multipipe": "^1.0.2",
|
||||
"through": "^2.3.8"
|
||||
}
|
||||
},
|
||||
"create-hash": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.1",
|
||||
@ -4671,7 +4516,7 @@
|
||||
},
|
||||
"create-hmac": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||
"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.3",
|
||||
@ -5015,14 +4860,6 @@
|
||||
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
|
||||
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg=="
|
||||
},
|
||||
"cssstyle": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.3.1.tgz",
|
||||
"integrity": "sha512-tNvaxM5blOnxanyxI6panOsnfiyLRj3HV4qjqqS45WPNS1usdYWRUQjqTEEELK73lpeP/1KoIGYUwrBn/VcECA==",
|
||||
"requires": {
|
||||
"cssom": "0.3.x"
|
||||
}
|
||||
},
|
||||
"csstype": {
|
||||
"version": "2.6.10",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.10.tgz",
|
||||
@ -5593,7 +5430,7 @@
|
||||
},
|
||||
"diffie-hellman": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
|
||||
"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
|
||||
"requires": {
|
||||
"bn.js": "^4.1.0",
|
||||
@ -5792,43 +5629,6 @@
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
|
||||
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
|
||||
},
|
||||
"duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
"integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
|
||||
"requires": {
|
||||
"readable-stream": "^2.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"duplexify": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
|
||||
@ -5919,23 +5719,6 @@
|
||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
||||
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
|
||||
},
|
||||
"emotion": {
|
||||
"version": "9.2.12",
|
||||
"resolved": "https://registry.npmjs.org/emotion/-/emotion-9.2.12.tgz",
|
||||
"integrity": "sha512-hcx7jppaI8VoXxIWEhxpDW7I+B4kq9RNzQLmsrF6LY8BGKqe2N+gFAQr0EfuFucFlPs2A9HM4+xNj4NeqEWIOQ==",
|
||||
"requires": {
|
||||
"babel-plugin-emotion": "^9.2.11",
|
||||
"create-emotion": "^9.2.12"
|
||||
}
|
||||
},
|
||||
"emotion-server": {
|
||||
"version": "9.2.12",
|
||||
"resolved": "https://registry.npmjs.org/emotion-server/-/emotion-server-9.2.12.tgz",
|
||||
"integrity": "sha512-Bhjdl7eNoIeiAVa2QPP5d+1nP/31SiO/K1P/qI9cdXCydg91NwGYmteqhhge8u7PF8fLGTEVQfcPwj21815eBw==",
|
||||
"requires": {
|
||||
"create-emotion-server": "^9.2.12"
|
||||
}
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
@ -6496,7 +6279,7 @@
|
||||
},
|
||||
"load-json-file": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
@ -7145,7 +6928,8 @@
|
||||
"find-root": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
|
||||
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
|
||||
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "2.1.0",
|
||||
@ -7220,13 +7004,6 @@
|
||||
"requires": {
|
||||
"tabbable": "^3.1.2",
|
||||
"xtend": "^4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
@ -7812,7 +7589,7 @@
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
@ -7892,18 +7669,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"html-tokenize": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/html-tokenize/-/html-tokenize-2.0.1.tgz",
|
||||
"integrity": "sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==",
|
||||
"requires": {
|
||||
"buffer-from": "~0.1.1",
|
||||
"inherits": "~2.0.1",
|
||||
"minimist": "~1.2.5",
|
||||
"readable-stream": "~1.0.27-1",
|
||||
"through2": "~0.4.1"
|
||||
}
|
||||
},
|
||||
"html-webpack-plugin": {
|
||||
"version": "4.0.0-beta.11",
|
||||
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz",
|
||||
@ -9661,11 +9426,6 @@
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"lower-case": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
||||
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -9767,7 +9527,7 @@
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||
},
|
||||
"mem": {
|
||||
@ -10171,15 +9931,6 @@
|
||||
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
|
||||
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
|
||||
},
|
||||
"multipipe": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/multipipe/-/multipipe-1.0.2.tgz",
|
||||
"integrity": "sha1-zBPv2DPJzamfIk+GhGG44aP9k50=",
|
||||
"requires": {
|
||||
"duplexer2": "^0.1.2",
|
||||
"object-assign": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
|
||||
@ -10262,17 +10013,9 @@
|
||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
|
||||
},
|
||||
"no-case": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
|
||||
"integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
|
||||
"requires": {
|
||||
"lower-case": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz",
|
||||
"integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -10415,14 +10158,6 @@
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.55.tgz",
|
||||
"integrity": "sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w=="
|
||||
},
|
||||
"nopt": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
|
||||
"integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=",
|
||||
"requires": {
|
||||
"abbrev": "1"
|
||||
}
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||
@ -10545,11 +10280,6 @@
|
||||
"es-abstract": "^1.17.5"
|
||||
}
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
|
||||
"integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY="
|
||||
},
|
||||
"object-path": {
|
||||
"version": "0.11.4",
|
||||
"resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz",
|
||||
@ -10700,7 +10430,7 @@
|
||||
"dependencies": {
|
||||
"ansi-escapes": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
|
||||
"integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=",
|
||||
"dev": true
|
||||
},
|
||||
@ -10746,7 +10476,7 @@
|
||||
},
|
||||
"external-editor": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -10808,7 +10538,7 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"dev": true
|
||||
},
|
||||
@ -10829,7 +10559,7 @@
|
||||
},
|
||||
"opn": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz",
|
||||
"resolved": "http://registry.npmjs.org/opn/-/opn-4.0.2.tgz",
|
||||
"integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -13284,7 +13014,7 @@
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "1.0.34",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
|
||||
"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
@ -13789,7 +13519,7 @@
|
||||
},
|
||||
"safe-regex": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
|
||||
"requires": {
|
||||
"ret": "~0.1.10"
|
||||
@ -14053,7 +13783,7 @@
|
||||
},
|
||||
"sha.js": {
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
@ -14814,7 +14544,7 @@
|
||||
},
|
||||
"strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
|
||||
},
|
||||
"strip-indent": {
|
||||
@ -15133,18 +14863,9 @@
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"through2": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz",
|
||||
"integrity": "sha1-2/WGYDEVHsg1K7bE22SiKSqEC5s=",
|
||||
"requires": {
|
||||
"readable-stream": "~1.0.17",
|
||||
"xtend": "~2.1.1"
|
||||
}
|
||||
},
|
||||
"thunky": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
|
||||
@ -15237,14 +14958,6 @@
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"touch": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/touch/-/touch-2.0.2.tgz",
|
||||
"integrity": "sha512-qjNtvsFXTRq7IuMLweVgFxmEuQ6gLbRs2jQxL80TtZ31dEKWYIxRXquij6w6VimyDek5hD3PytljHmEtAs2u0A==",
|
||||
"requires": {
|
||||
"nopt": "~1.0.10"
|
||||
}
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||
@ -15458,11 +15171,6 @@
|
||||
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
|
||||
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="
|
||||
},
|
||||
"upper-case": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
|
||||
"integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||
@ -16629,12 +16337,9 @@
|
||||
}
|
||||
},
|
||||
"xtend": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
|
||||
"integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
|
||||
"requires": {
|
||||
"object-keys": "~0.4.0"
|
||||
}
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
|
||||
@ -4,10 +4,9 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@lingui/react": "^2.9.1",
|
||||
"@patternfly/patternfly": "^2.71.6",
|
||||
"@patternfly/react-core": "^3.158.1",
|
||||
"@patternfly/react-icons": "^3.15.17",
|
||||
"@patternfly/react-tokens": "^2.8.14",
|
||||
"@patternfly/patternfly": "^4.10.31",
|
||||
"@patternfly/react-core": "4.18.14",
|
||||
"@patternfly/react-icons": "^4.3.5",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
|
||||
@ -8,6 +8,8 @@ import {
|
||||
InfoCircleIcon,
|
||||
TimesCircleIcon,
|
||||
} from '@patternfly/react-icons';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Header = styled.div`
|
||||
@ -17,11 +19,14 @@ const Header = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export default function AlertModal({
|
||||
function AlertModal({
|
||||
i18n,
|
||||
isOpen = null,
|
||||
title,
|
||||
label,
|
||||
variant,
|
||||
children,
|
||||
i18nHash,
|
||||
...props
|
||||
}) {
|
||||
const variantIcons = {
|
||||
@ -60,16 +65,19 @@ export default function AlertModal({
|
||||
const customHeader = (
|
||||
<Header>
|
||||
{variant ? variantIcons[variant] : null}
|
||||
<Title size="2xl">{title}</Title>
|
||||
<Title id="alert-modal-header-label" size="2xl" headingLevel="h2">
|
||||
{title}
|
||||
</Title>
|
||||
</Header>
|
||||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
header={customHeader}
|
||||
isFooterLeftAligned
|
||||
aria-label={label || i18n._(t`Alert modal`)}
|
||||
aria-labelledby="alert-modal-header-label"
|
||||
isOpen={Boolean(isOpen)}
|
||||
isSmall
|
||||
variant="small"
|
||||
title={title}
|
||||
{...props}
|
||||
>
|
||||
@ -77,3 +85,5 @@ export default function AlertModal({
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default withI18n()(AlertModal);
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
|
||||
import AlertModal from './AlertModal';
|
||||
|
||||
describe('AlertModal', () => {
|
||||
test('renders the expected content', () => {
|
||||
const wrapper = mount(
|
||||
const wrapper = mountWithContexts(
|
||||
<AlertModal title="Danger!">Are you sure?</AlertModal>
|
||||
);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
|
||||
@ -43,7 +43,7 @@ class AnsibleSelect extends React.Component {
|
||||
onChange={this.onSelectChange}
|
||||
onBlur={onBlur}
|
||||
aria-label={i18n._(t`Select Input`)}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
className={className}
|
||||
isDisabled={isDisabled}
|
||||
>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useHistory, useLocation, withRouter } from 'react-router-dom';
|
||||
import { global_breakpoint_md } from '@patternfly/react-tokens';
|
||||
import {
|
||||
Nav,
|
||||
NavList,
|
||||
@ -41,15 +40,10 @@ function AppContainer({ i18n, navRouteConfig = [], children }) {
|
||||
const [config, setConfig] = useState({});
|
||||
const [configError, setConfigError] = useState(null);
|
||||
const [isAboutModalOpen, setIsAboutModalOpen] = useState(false);
|
||||
const [isNavOpen, setIsNavOpen] = useState(
|
||||
typeof window !== 'undefined' &&
|
||||
window.innerWidth >= parseInt(global_breakpoint_md.value, 10)
|
||||
);
|
||||
|
||||
const handleAboutModalOpen = () => setIsAboutModalOpen(true);
|
||||
const handleAboutModalClose = () => setIsAboutModalOpen(false);
|
||||
const handleConfigErrorClose = () => setConfigError(null);
|
||||
const handleNavToggle = () => setIsNavOpen(!isNavOpen);
|
||||
|
||||
const handleLogout = async () => {
|
||||
await RootAPI.logout();
|
||||
@ -79,10 +73,9 @@ function AppContainer({ i18n, navRouteConfig = [], children }) {
|
||||
const header = (
|
||||
<PageHeader
|
||||
showNavToggle
|
||||
onNavToggle={handleNavToggle}
|
||||
logo={<BrandLogo />}
|
||||
logoProps={{ href: '/' }}
|
||||
toolbar={
|
||||
headerTools={
|
||||
<PageHeaderToolbar
|
||||
loggedInUser={config?.me}
|
||||
isAboutDisabled={!config?.version}
|
||||
@ -95,7 +88,6 @@ function AppContainer({ i18n, navRouteConfig = [], children }) {
|
||||
|
||||
const sidebar = (
|
||||
<PageSidebar
|
||||
isNavOpen={isNavOpen}
|
||||
theme="dark"
|
||||
nav={
|
||||
<Nav aria-label={i18n._(t`Navigation`)} theme="dark">
|
||||
@ -116,7 +108,7 @@ function AppContainer({ i18n, navRouteConfig = [], children }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Page usecondensed="True" header={header} sidebar={sidebar}>
|
||||
<Page isManagedSidebar header={header} sidebar={sidebar}>
|
||||
<ConfigProvider value={config}>{children}</ConfigProvider>
|
||||
</Page>
|
||||
<About
|
||||
|
||||
@ -7,9 +7,9 @@ import {
|
||||
DropdownItem,
|
||||
DropdownToggle,
|
||||
DropdownPosition,
|
||||
Toolbar,
|
||||
ToolbarGroup,
|
||||
ToolbarItem,
|
||||
PageHeaderTools,
|
||||
PageHeaderToolsGroup,
|
||||
PageHeaderToolsItem,
|
||||
Tooltip,
|
||||
} from '@patternfly/react-core';
|
||||
import { QuestionCircleIcon, UserIcon } from '@patternfly/react-icons';
|
||||
@ -62,10 +62,10 @@ class PageHeaderToolbar extends Component {
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Toolbar>
|
||||
<ToolbarGroup>
|
||||
<PageHeaderTools>
|
||||
<PageHeaderToolsGroup>
|
||||
<Tooltip position="left" content={<div>{i18n._(t`Info`)}</div>}>
|
||||
<ToolbarItem>
|
||||
<PageHeaderToolsItem>
|
||||
<Dropdown
|
||||
isPlain
|
||||
isOpen={isHelpOpen}
|
||||
@ -93,10 +93,10 @@ class PageHeaderToolbar extends Component {
|
||||
</DropdownItem>,
|
||||
]}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
</PageHeaderToolsItem>
|
||||
</Tooltip>
|
||||
<Tooltip position="left" content={<div>{i18n._(t`User`)}</div>}>
|
||||
<ToolbarItem>
|
||||
<PageHeaderToolsItem>
|
||||
<Dropdown
|
||||
id="toolbar-user-dropdown"
|
||||
isPlain
|
||||
@ -134,10 +134,10 @@ class PageHeaderToolbar extends Component {
|
||||
</DropdownItem>,
|
||||
]}
|
||||
/>
|
||||
</ToolbarItem>
|
||||
</PageHeaderToolsItem>
|
||||
</Tooltip>
|
||||
</ToolbarGroup>
|
||||
</Toolbar>
|
||||
</PageHeaderToolsGroup>
|
||||
</PageHeaderTools>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,9 +74,9 @@ function AssociateModal({
|
||||
return (
|
||||
<Fragment>
|
||||
<Modal
|
||||
isFooterLeftAligned
|
||||
isLarge
|
||||
variant="large"
|
||||
title={title}
|
||||
aria-label={i18n._(t`Association modal`)}
|
||||
isOpen={isModalOpen}
|
||||
onClose={handleClose}
|
||||
actions={[
|
||||
|
||||
@ -1,18 +1,10 @@
|
||||
import React, { Fragment } from 'react';
|
||||
|
||||
import { BackgroundImage, BackgroundImageSrc } from '@patternfly/react-core';
|
||||
|
||||
const backgroundImageConfig = {
|
||||
[BackgroundImageSrc.xs]: './images/pfbg_576.jpg',
|
||||
[BackgroundImageSrc.xs2x]: './images/pfbg_576@2x.jpg',
|
||||
[BackgroundImageSrc.sm]: './images/pfbg_768.jpg',
|
||||
[BackgroundImageSrc.sm2x]: './images/pfbg_768@2x.jpg',
|
||||
[BackgroundImageSrc.lg]: './images/pfbg_2000.jpg',
|
||||
};
|
||||
import { BackgroundImage } from '@patternfly/react-core';
|
||||
|
||||
export default ({ children }) => (
|
||||
<Fragment>
|
||||
<BackgroundImage src={backgroundImageConfig} />
|
||||
<BackgroundImage />
|
||||
{children}
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@ -11,7 +11,7 @@ describe('Background', () => {
|
||||
</Background>
|
||||
);
|
||||
expect(wrapper).toHaveLength(1);
|
||||
expect(wrapper.find('BackgroundImage')).toHaveLength(1);
|
||||
expect(wrapper.find('.pf-c-background-image')).toHaveLength(1);
|
||||
expect(wrapper.find('#test')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -30,19 +30,21 @@ const Breadcrumbs = ({ breadcrumbConfig }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Crumb = ({ breadcrumbConfig }) => {
|
||||
const Crumb = ({ breadcrumbConfig, showDivider }) => {
|
||||
const match = useRouteMatch();
|
||||
const crumb = breadcrumbConfig[match.url];
|
||||
|
||||
let crumbElement = (
|
||||
<BreadcrumbItem key={match.url}>
|
||||
<BreadcrumbItem key={match.url} showDivider={showDivider}>
|
||||
<Link to={match.url}>{crumb}</Link>
|
||||
</BreadcrumbItem>
|
||||
);
|
||||
|
||||
if (match.isExact) {
|
||||
crumbElement = (
|
||||
<BreadcrumbHeading key="breadcrumb-heading">{crumb}</BreadcrumbHeading>
|
||||
<BreadcrumbHeading key="breadcrumb-heading" showDivider={showDivider}>
|
||||
{crumb}
|
||||
</BreadcrumbHeading>
|
||||
);
|
||||
}
|
||||
|
||||
@ -54,7 +56,7 @@ const Crumb = ({ breadcrumbConfig }) => {
|
||||
<Fragment>
|
||||
{crumbElement}
|
||||
<Route path={`${match.url}/:path`}>
|
||||
<Crumb breadcrumbConfig={breadcrumbConfig} />
|
||||
<Crumb breadcrumbConfig={breadcrumbConfig} showDivider />
|
||||
</Route>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
import { CardHeader } from '@patternfly/react-core';
|
||||
|
||||
const TabbedCardHeader = styled(CardHeader)`
|
||||
--pf-c-card--first-child--PaddingTop: 0;
|
||||
--pf-c-card--child--PaddingLeft: 0;
|
||||
--pf-c-card--child--PaddingRight: 0;
|
||||
--pf-c-card__header--not-last-child--PaddingBottom: 24px;
|
||||
--pf-c-card__header--not-last-child--PaddingBottom: 0;
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export default TabbedCardHeader;
|
||||
@ -1,3 +1,2 @@
|
||||
export { default as TabbedCardHeader } from './TabbedCardHeader';
|
||||
export { default as CardBody } from './CardBody';
|
||||
export { default as CardActionsRow } from './CardActionsRow';
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
import React from 'react';
|
||||
import { string } from 'prop-types';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button } from '@patternfly/react-core';
|
||||
import { TimesIcon } from '@patternfly/react-icons';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
|
||||
function CardCloseButton({ linkTo, i18n, i18nHash, ...props }) {
|
||||
if (linkTo) {
|
||||
return (
|
||||
<Link
|
||||
className="pf-c-button pf-m-plain"
|
||||
aria-label={i18n._(t`Close`)}
|
||||
title={i18n._(t`Close`)}
|
||||
to={linkTo}
|
||||
{...props}
|
||||
>
|
||||
<TimesIcon />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Button variant="plain" aria-label={i18n._(t`Close`)} {...props}>
|
||||
<TimesIcon />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
CardCloseButton.propTypes = {
|
||||
linkTo: string,
|
||||
};
|
||||
CardCloseButton.defaultProps = {
|
||||
linkTo: null,
|
||||
};
|
||||
|
||||
export default withI18n()(CardCloseButton);
|
||||
@ -1,23 +0,0 @@
|
||||
import React from 'react';
|
||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
import CardCloseButton from './CardCloseButton';
|
||||
|
||||
describe('<CardCloseButton>', () => {
|
||||
test('should render close button', () => {
|
||||
const wrapper = mountWithContexts(<CardCloseButton />);
|
||||
const button = wrapper.find('Button');
|
||||
expect(button).toHaveLength(1);
|
||||
expect(button.prop('variant')).toBe('plain');
|
||||
expect(button.prop('aria-label')).toBe('Close');
|
||||
expect(wrapper.find('Link')).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('should render close link when `linkTo` prop provided', () => {
|
||||
const wrapper = mountWithContexts(<CardCloseButton linkTo="/foo" />);
|
||||
expect(wrapper.find('Button')).toHaveLength(0);
|
||||
const link = wrapper.find('Link');
|
||||
expect(link).toHaveLength(1);
|
||||
expect(link.prop('to')).toEqual('/foo');
|
||||
expect(link.prop('aria-label')).toEqual('Close');
|
||||
});
|
||||
});
|
||||
@ -1 +0,0 @@
|
||||
export { default } from './CardCloseButton';
|
||||
@ -4,7 +4,7 @@ import { t } from '@lingui/macro';
|
||||
import { ChipGroup as PFChipGroup } from '@patternfly/react-core';
|
||||
import { number, shape } from 'prop-types';
|
||||
|
||||
function ChipGroup({ i18n, numChips, totalChips, ...props }) {
|
||||
function ChipGroup({ i18n, numChips, totalChips, i18nHash, ...props }) {
|
||||
return (
|
||||
<PFChipGroup
|
||||
{...props}
|
||||
|
||||
@ -39,7 +39,7 @@ function VariablesDetail({ value, label, rows, fullHeight }) {
|
||||
fullWidth
|
||||
css="grid-column: 1 / -1"
|
||||
>
|
||||
<Split gutter="sm">
|
||||
<Split hasGutter>
|
||||
<SplitItem>
|
||||
<div className="pf-c-form__label">
|
||||
<span
|
||||
|
||||
@ -35,7 +35,7 @@ function VariablesField({
|
||||
return (
|
||||
<div className="pf-c-form__group">
|
||||
<FieldHeader>
|
||||
<Split gutter="sm">
|
||||
<Split hasGutter>
|
||||
<SplitItem>
|
||||
<label htmlFor={id} className="pf-c-form__label">
|
||||
<span className="pf-c-form__label-text">{label}</span>
|
||||
|
||||
@ -35,7 +35,7 @@ function VariablesInput(props) {
|
||||
|
||||
return (
|
||||
<div className={`pf-c-form__group ${className || ''}`}>
|
||||
<Split gutter="sm">
|
||||
<Split hasGutter>
|
||||
<SplitItem>
|
||||
<label htmlFor={id} className="pf-c-form__label">
|
||||
{label}
|
||||
|
||||
@ -12,7 +12,9 @@ import { CubesIcon } from '@patternfly/react-icons';
|
||||
const ContentEmpty = ({ i18n, title = '', message = '' }) => (
|
||||
<EmptyState variant="full">
|
||||
<EmptyStateIcon icon={CubesIcon} />
|
||||
<Title size="lg">{title || i18n._(t`No items found.`)}</Title>
|
||||
<Title size="lg" headingLevel="h3">
|
||||
{title || i18n._(t`No items found.`)}
|
||||
</Title>
|
||||
<EmptyStateBody>{message}</EmptyStateBody>
|
||||
</EmptyState>
|
||||
);
|
||||
|
||||
@ -35,7 +35,7 @@ function ContentError({ error, children, isNotFound, i18n }) {
|
||||
) : (
|
||||
<EmptyState variant="full">
|
||||
<EmptyStateIcon icon={ExclamationTriangleIcon} />
|
||||
<Title size="lg">
|
||||
<Title size="lg" headingLevel="h3">
|
||||
{is404 ? i18n._(t`Not Found`) : i18n._(t`Something went wrong...`)}
|
||||
</Title>
|
||||
<EmptyStateBody>
|
||||
|
||||
@ -6,7 +6,7 @@ import { Chip } from '@patternfly/react-core';
|
||||
import { Credential } from '../../types';
|
||||
import { toTitleCase } from '../../util/strings';
|
||||
|
||||
function CredentialChip({ credential, i18n, ...props }) {
|
||||
function CredentialChip({ credential, i18n, i18nHash, ...props }) {
|
||||
let type;
|
||||
if (credential.cloud) {
|
||||
type = i18n._(t`Cloud`);
|
||||
|
||||
@ -2,30 +2,21 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Checkbox } from '@patternfly/react-core';
|
||||
import styled from 'styled-components';
|
||||
import { SearchIcon } from '@patternfly/react-icons';
|
||||
import {
|
||||
DataToolbar,
|
||||
DataToolbarContent as _DataToolbarContent,
|
||||
DataToolbarGroup as _DataToolbarGroup,
|
||||
DataToolbarItem,
|
||||
DataToolbarToggleGroup,
|
||||
} from '@patternfly/react-core/dist/umd/experimental';
|
||||
Checkbox,
|
||||
Toolbar,
|
||||
ToolbarContent,
|
||||
ToolbarGroup,
|
||||
ToolbarItem,
|
||||
ToolbarToggleGroup,
|
||||
} from '@patternfly/react-core';
|
||||
import { SearchIcon } from '@patternfly/react-icons';
|
||||
import ExpandCollapse from '../ExpandCollapse';
|
||||
import Search from '../Search';
|
||||
import Sort from '../Sort';
|
||||
|
||||
import { SearchColumns, SortColumns, QSConfig } from '../../types';
|
||||
|
||||
const DataToolbarContent = styled(_DataToolbarContent)`
|
||||
--pf-c-data-toolbar__content--PaddingLeft: 24px;
|
||||
--pf-c-data-toolbar__content--PaddingRight: 8px;
|
||||
`;
|
||||
const DataToolbarGroup = styled(_DataToolbarGroup)`
|
||||
--pf-c-data-toolbar__group--spacer: 24px;
|
||||
`;
|
||||
|
||||
class DataListToolbar extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
@ -49,26 +40,26 @@ class DataListToolbar extends React.Component {
|
||||
|
||||
const showExpandCollapse = onCompact && onExpand;
|
||||
return (
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${qsConfig.namespace}-list-toolbar`}
|
||||
clearAllFilters={clearAllFilters}
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
{showSelectAll && (
|
||||
<DataToolbarGroup>
|
||||
<DataToolbarItem>
|
||||
<ToolbarGroup>
|
||||
<ToolbarItem>
|
||||
<Checkbox
|
||||
isChecked={isAllSelected}
|
||||
onChange={onSelectAll}
|
||||
aria-label={i18n._(t`Select all`)}
|
||||
id="select-all"
|
||||
/>
|
||||
</DataToolbarItem>
|
||||
</DataToolbarGroup>
|
||||
</ToolbarItem>
|
||||
</ToolbarGroup>
|
||||
)}
|
||||
<DataToolbarToggleGroup toggleIcon={<SearchIcon />} breakpoint="lg">
|
||||
<DataToolbarItem>
|
||||
<ToolbarToggleGroup toggleIcon={<SearchIcon />} breakpoint="lg">
|
||||
<ToolbarItem>
|
||||
<Search
|
||||
qsConfig={qsConfig}
|
||||
columns={searchColumns}
|
||||
@ -76,31 +67,31 @@ class DataListToolbar extends React.Component {
|
||||
onReplaceSearch={onReplaceSearch}
|
||||
onRemove={onRemove}
|
||||
/>
|
||||
</DataToolbarItem>
|
||||
<DataToolbarItem>
|
||||
</ToolbarItem>
|
||||
<ToolbarItem>
|
||||
<Sort qsConfig={qsConfig} columns={sortColumns} onSort={onSort} />
|
||||
</DataToolbarItem>
|
||||
</DataToolbarToggleGroup>
|
||||
</ToolbarItem>
|
||||
</ToolbarToggleGroup>
|
||||
{showExpandCollapse && (
|
||||
<DataToolbarGroup>
|
||||
<ToolbarGroup>
|
||||
<Fragment>
|
||||
<DataToolbarItem>
|
||||
<ToolbarItem>
|
||||
<ExpandCollapse
|
||||
isCompact={isCompact}
|
||||
onCompact={onCompact}
|
||||
onExpand={onExpand}
|
||||
/>
|
||||
</DataToolbarItem>
|
||||
</ToolbarItem>
|
||||
</Fragment>
|
||||
</DataToolbarGroup>
|
||||
</ToolbarGroup>
|
||||
)}
|
||||
<DataToolbarGroup>
|
||||
<ToolbarGroup>
|
||||
{additionalControls.map(control => (
|
||||
<DataToolbarItem key={control.key}>{control}</DataToolbarItem>
|
||||
<ToolbarItem key={control.key}>{control}</ToolbarItem>
|
||||
))}
|
||||
</DataToolbarGroup>
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>
|
||||
</ToolbarGroup>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import { t } from '@lingui/macro';
|
||||
import {
|
||||
Card as PFCard,
|
||||
CardBody as PFCardBody,
|
||||
Expandable as PFExpandable,
|
||||
ExpandableSection as PFExpandable,
|
||||
} from '@patternfly/react-core';
|
||||
import getErrorMessage from './getErrorMessage';
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ describe('ErrorDetail', () => {
|
||||
}
|
||||
/>
|
||||
);
|
||||
wrapper.find('Expandable').prop('onToggle')();
|
||||
wrapper.find('ExpandableSection').prop('onToggle')();
|
||||
wrapper.update();
|
||||
});
|
||||
});
|
||||
|
||||
@ -29,14 +29,14 @@ function FormField(props) {
|
||||
helperText={helperText}
|
||||
helperTextInvalid={meta.error}
|
||||
isRequired={isRequired}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={label}
|
||||
>
|
||||
<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />
|
||||
<TextArea
|
||||
id={id}
|
||||
isRequired={isRequired}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
resizeOrientation="vertical"
|
||||
{...rest}
|
||||
{...field}
|
||||
@ -51,14 +51,14 @@ function FormField(props) {
|
||||
helperText={helperText}
|
||||
helperTextInvalid={meta.error}
|
||||
isRequired={isRequired}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={label}
|
||||
>
|
||||
<FieldTooltip content={tooltip} maxWidth={tooltipMaxWidth} />
|
||||
<TextInput
|
||||
id={id}
|
||||
isRequired={isRequired}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
{...rest}
|
||||
{...field}
|
||||
type={type}
|
||||
|
||||
@ -14,7 +14,7 @@ function PasswordField(props) {
|
||||
fieldId={id}
|
||||
helperTextInvalid={meta.error}
|
||||
isRequired={isRequired}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={label}
|
||||
>
|
||||
<InputGroup>
|
||||
|
||||
@ -44,7 +44,7 @@ function PasswordInput(props) {
|
||||
value={field.value === '$encrypted$' ? '' : field.value}
|
||||
isDisabled={isDisabled}
|
||||
isRequired={isRequired}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
type={inputType}
|
||||
onChange={(_, event) => {
|
||||
field.onChange(event);
|
||||
|
||||
@ -27,7 +27,9 @@ const InventoryLookupField = withI18n()(({ i18n, host }) => {
|
||||
label={i18n._(t`Inventory`)}
|
||||
isRequired
|
||||
fieldId="inventory-lookup"
|
||||
isValid={!inventoryMeta.touched || !inventoryMeta.error}
|
||||
validated={
|
||||
!inventoryMeta.touched || !inventoryMeta.error ? 'default' : 'error'
|
||||
}
|
||||
helperTextInvalid={inventoryMeta.error}
|
||||
>
|
||||
<FieldTooltip
|
||||
|
||||
@ -101,7 +101,7 @@ function JobTypeField({ i18n }) {
|
||||
<FormGroup
|
||||
fieldId="propmt-job-type"
|
||||
label={i18n._(t`Job Type`)}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
>
|
||||
<FieldTooltip
|
||||
content={i18n._(t`For job templates, select run to execute the playbook.
|
||||
@ -132,7 +132,7 @@ function VerbosityField({ i18n }) {
|
||||
return (
|
||||
<FormGroup
|
||||
fieldId="prompt-verbosity"
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={i18n._(t`Verbosity`)}
|
||||
>
|
||||
<FieldTooltip
|
||||
|
||||
@ -96,7 +96,7 @@ function MultipleChoiceField({ question }) {
|
||||
fieldId={id}
|
||||
helperTextInvalid={meta.error}
|
||||
isRequired={question.required}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={question.question_name}
|
||||
>
|
||||
<FieldTooltip content={question.question_description} />
|
||||
@ -124,7 +124,7 @@ function MultiSelectField({ question }) {
|
||||
fieldId={id}
|
||||
helperTextInvalid={meta.error}
|
||||
isRequired={question.required}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={question.question_name}
|
||||
>
|
||||
<FieldTooltip content={question.question_description} />
|
||||
@ -139,7 +139,7 @@ function MultiSelectField({ question }) {
|
||||
helpers.setValue(field.value.concat(option));
|
||||
}
|
||||
}}
|
||||
isExpanded={isOpen}
|
||||
isOpen={isOpen}
|
||||
selections={field.value}
|
||||
>
|
||||
{question.choices.split('\n').map(opt => (
|
||||
|
||||
@ -2,10 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
DataToolbar,
|
||||
DataToolbarContent,
|
||||
} from '@patternfly/react-core/dist/umd/experimental';
|
||||
import { Toolbar, ToolbarContent } from '@patternfly/react-core';
|
||||
import DataListToolbar from '../DataListToolbar';
|
||||
|
||||
import {
|
||||
@ -107,17 +104,17 @@ class ListHeader extends React.Component {
|
||||
return (
|
||||
<Fragment>
|
||||
{isEmpty ? (
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${qsConfig.namespace}-list-toolbar`}
|
||||
clearAllFilters={this.handleRemoveAll}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<EmptyStateControlsWrapper>
|
||||
{emptyStateControls}
|
||||
</EmptyStateControlsWrapper>
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
) : (
|
||||
<Fragment>
|
||||
{renderToolbar({
|
||||
|
||||
@ -84,7 +84,7 @@ function CredentialLookup({
|
||||
<FormGroup
|
||||
fieldId="credential"
|
||||
isRequired={required}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={label}
|
||||
helperTextInvalid={helperTextInvalid}
|
||||
>
|
||||
|
||||
@ -142,9 +142,9 @@ function Lookup(props) {
|
||||
</ChipHolder>
|
||||
</InputGroup>
|
||||
<Modal
|
||||
isFooterLeftAligned
|
||||
isLarge
|
||||
variant="large"
|
||||
title={i18n._(t`Select ${header || i18n._(t`Items`)}`)}
|
||||
aria-label={i18n._(t`Lookup modal`)}
|
||||
isOpen={isModalOpen}
|
||||
onClose={closeModal}
|
||||
actions={[
|
||||
|
||||
@ -81,7 +81,7 @@ describe('<MultiCredentialsLookup />', () => {
|
||||
});
|
||||
const chip = wrapper.find('CredentialChip');
|
||||
expect(chip).toHaveLength(5);
|
||||
const button = chip.at(1).find('ChipButton');
|
||||
const button = chip.at(1).find('Chip Button');
|
||||
await act(async () => {
|
||||
button.invoke('onClick')();
|
||||
});
|
||||
|
||||
@ -49,7 +49,7 @@ function OrganizationLookup({
|
||||
fieldId="organization"
|
||||
helperTextInvalid={helperTextInvalid}
|
||||
isRequired={required}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={i18n._(t`Organization`)}
|
||||
>
|
||||
<Lookup
|
||||
|
||||
@ -63,7 +63,7 @@ function ProjectLookup({
|
||||
fieldId="project"
|
||||
helperTextInvalid={helperTextInvalid}
|
||||
isRequired={required}
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={i18n._(t`Project`)}
|
||||
>
|
||||
{tooltip && <FieldTooltip content={tooltip} />}
|
||||
|
||||
@ -50,8 +50,8 @@ function TagMultiSelect({ onChange, value }) {
|
||||
return name;
|
||||
}}
|
||||
selections={selections}
|
||||
isExpanded={isExpanded}
|
||||
ariaLabelledBy="tag-select"
|
||||
isOpen={isExpanded}
|
||||
aria-labelledby="tag-select"
|
||||
>
|
||||
{renderOptions(options)}
|
||||
</Select>
|
||||
|
||||
@ -17,7 +17,7 @@ describe('<TagMultiSelect />', () => {
|
||||
it('should not treat empty string as an option', () => {
|
||||
const wrapper = mount(<TagMultiSelect value="" onChange={jest.fn()} />);
|
||||
wrapper.find('input').simulate('focus');
|
||||
expect(wrapper.find('Select').prop('isExpanded')).toEqual(true);
|
||||
expect(wrapper.find('Select').prop('isOpen')).toEqual(true);
|
||||
expect(wrapper.find('SelectOption')).toHaveLength(0);
|
||||
});
|
||||
|
||||
|
||||
@ -264,7 +264,7 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe
|
||||
className="pf-c-data-list__item-action sc-bwzfXH llKtln"
|
||||
rowid="items-list-item-9000"
|
||||
>
|
||||
<Component
|
||||
<Switch
|
||||
aria-label="Toggle notification start"
|
||||
id="notification-9000-started-toggle"
|
||||
isChecked={false}
|
||||
@ -273,73 +273,43 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe
|
||||
labelOff="Start"
|
||||
onChange={[Function]}
|
||||
>
|
||||
<ComponentWithOuia
|
||||
component={[Function]}
|
||||
componentProps={
|
||||
Object {
|
||||
"aria-label": "Toggle notification start",
|
||||
"id": "notification-9000-started-toggle",
|
||||
"isChecked": false,
|
||||
"isDisabled": false,
|
||||
"label": "Start",
|
||||
"labelOff": "Start",
|
||||
"onChange": [Function],
|
||||
}
|
||||
}
|
||||
consumerContext={null}
|
||||
<label
|
||||
className="pf-c-switch"
|
||||
data-ouia-component-id={0}
|
||||
data-ouia-component-type="PF4/Switch"
|
||||
data-ouia-safe={true}
|
||||
htmlFor="notification-9000-started-toggle"
|
||||
>
|
||||
<Switch
|
||||
<input
|
||||
aria-label="Toggle notification start"
|
||||
className=""
|
||||
aria-labelledby={null}
|
||||
checked={false}
|
||||
className="pf-c-switch__input"
|
||||
disabled={false}
|
||||
id="notification-9000-started-toggle"
|
||||
isChecked={false}
|
||||
isDisabled={false}
|
||||
label="Start"
|
||||
labelOff="Start"
|
||||
onChange={[Function]}
|
||||
ouiaContext={
|
||||
Object {
|
||||
"isOuia": false,
|
||||
"ouiaId": null,
|
||||
}
|
||||
}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="pf-c-switch__toggle"
|
||||
/>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-on"
|
||||
id={null}
|
||||
>
|
||||
<label
|
||||
className="pf-c-switch"
|
||||
htmlFor="notification-9000-started-toggle"
|
||||
>
|
||||
<input
|
||||
aria-label="Toggle notification start"
|
||||
aria-labelledby={null}
|
||||
checked={false}
|
||||
className="pf-c-switch__input"
|
||||
disabled={false}
|
||||
id="notification-9000-started-toggle"
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="pf-c-switch__toggle"
|
||||
/>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-on"
|
||||
id={null}
|
||||
>
|
||||
Start
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-off"
|
||||
id={null}
|
||||
>
|
||||
Start
|
||||
</span>
|
||||
</label>
|
||||
</Switch>
|
||||
</ComponentWithOuia>
|
||||
</Component>
|
||||
<Component
|
||||
Start
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-off"
|
||||
id={null}
|
||||
>
|
||||
Start
|
||||
</span>
|
||||
</label>
|
||||
</Switch>
|
||||
<Switch
|
||||
aria-label="Toggle notification success"
|
||||
id="notification-9000-success-toggle"
|
||||
isChecked={false}
|
||||
@ -348,73 +318,43 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe
|
||||
labelOff="Success"
|
||||
onChange={[Function]}
|
||||
>
|
||||
<ComponentWithOuia
|
||||
component={[Function]}
|
||||
componentProps={
|
||||
Object {
|
||||
"aria-label": "Toggle notification success",
|
||||
"id": "notification-9000-success-toggle",
|
||||
"isChecked": false,
|
||||
"isDisabled": false,
|
||||
"label": "Success",
|
||||
"labelOff": "Success",
|
||||
"onChange": [Function],
|
||||
}
|
||||
}
|
||||
consumerContext={null}
|
||||
<label
|
||||
className="pf-c-switch"
|
||||
data-ouia-component-id={1}
|
||||
data-ouia-component-type="PF4/Switch"
|
||||
data-ouia-safe={true}
|
||||
htmlFor="notification-9000-success-toggle"
|
||||
>
|
||||
<Switch
|
||||
<input
|
||||
aria-label="Toggle notification success"
|
||||
className=""
|
||||
aria-labelledby={null}
|
||||
checked={false}
|
||||
className="pf-c-switch__input"
|
||||
disabled={false}
|
||||
id="notification-9000-success-toggle"
|
||||
isChecked={false}
|
||||
isDisabled={false}
|
||||
label="Success"
|
||||
labelOff="Success"
|
||||
onChange={[Function]}
|
||||
ouiaContext={
|
||||
Object {
|
||||
"isOuia": false,
|
||||
"ouiaId": null,
|
||||
}
|
||||
}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="pf-c-switch__toggle"
|
||||
/>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-on"
|
||||
id={null}
|
||||
>
|
||||
<label
|
||||
className="pf-c-switch"
|
||||
htmlFor="notification-9000-success-toggle"
|
||||
>
|
||||
<input
|
||||
aria-label="Toggle notification success"
|
||||
aria-labelledby={null}
|
||||
checked={false}
|
||||
className="pf-c-switch__input"
|
||||
disabled={false}
|
||||
id="notification-9000-success-toggle"
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="pf-c-switch__toggle"
|
||||
/>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-on"
|
||||
id={null}
|
||||
>
|
||||
Success
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-off"
|
||||
id={null}
|
||||
>
|
||||
Success
|
||||
</span>
|
||||
</label>
|
||||
</Switch>
|
||||
</ComponentWithOuia>
|
||||
</Component>
|
||||
<Component
|
||||
Success
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-off"
|
||||
id={null}
|
||||
>
|
||||
Success
|
||||
</span>
|
||||
</label>
|
||||
</Switch>
|
||||
<Switch
|
||||
aria-label="Toggle notification failure"
|
||||
id="notification-9000-error-toggle"
|
||||
isChecked={false}
|
||||
@ -423,72 +363,42 @@ exports[`<NotificationListItem canToggleNotifications /> initially renders succe
|
||||
labelOff="Failure"
|
||||
onChange={[Function]}
|
||||
>
|
||||
<ComponentWithOuia
|
||||
component={[Function]}
|
||||
componentProps={
|
||||
Object {
|
||||
"aria-label": "Toggle notification failure",
|
||||
"id": "notification-9000-error-toggle",
|
||||
"isChecked": false,
|
||||
"isDisabled": false,
|
||||
"label": "Failure",
|
||||
"labelOff": "Failure",
|
||||
"onChange": [Function],
|
||||
}
|
||||
}
|
||||
consumerContext={null}
|
||||
<label
|
||||
className="pf-c-switch"
|
||||
data-ouia-component-id={2}
|
||||
data-ouia-component-type="PF4/Switch"
|
||||
data-ouia-safe={true}
|
||||
htmlFor="notification-9000-error-toggle"
|
||||
>
|
||||
<Switch
|
||||
<input
|
||||
aria-label="Toggle notification failure"
|
||||
className=""
|
||||
aria-labelledby={null}
|
||||
checked={false}
|
||||
className="pf-c-switch__input"
|
||||
disabled={false}
|
||||
id="notification-9000-error-toggle"
|
||||
isChecked={false}
|
||||
isDisabled={false}
|
||||
label="Failure"
|
||||
labelOff="Failure"
|
||||
onChange={[Function]}
|
||||
ouiaContext={
|
||||
Object {
|
||||
"isOuia": false,
|
||||
"ouiaId": null,
|
||||
}
|
||||
}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="pf-c-switch__toggle"
|
||||
/>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-on"
|
||||
id={null}
|
||||
>
|
||||
<label
|
||||
className="pf-c-switch"
|
||||
htmlFor="notification-9000-error-toggle"
|
||||
>
|
||||
<input
|
||||
aria-label="Toggle notification failure"
|
||||
aria-labelledby={null}
|
||||
checked={false}
|
||||
className="pf-c-switch__input"
|
||||
disabled={false}
|
||||
id="notification-9000-error-toggle"
|
||||
onChange={[Function]}
|
||||
type="checkbox"
|
||||
/>
|
||||
<span
|
||||
className="pf-c-switch__toggle"
|
||||
/>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-on"
|
||||
id={null}
|
||||
>
|
||||
Failure
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-off"
|
||||
id={null}
|
||||
>
|
||||
Failure
|
||||
</span>
|
||||
</label>
|
||||
</Switch>
|
||||
</ComponentWithOuia>
|
||||
</Component>
|
||||
Failure
|
||||
</span>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="pf-c-switch__label pf-m-off"
|
||||
id={null}
|
||||
>
|
||||
Failure
|
||||
</span>
|
||||
</label>
|
||||
</Switch>
|
||||
</div>
|
||||
</DataListAction>
|
||||
</StyledComponent>
|
||||
|
||||
@ -18,7 +18,7 @@ import DataListToolbar from '../DataListToolbar';
|
||||
import { QSConfig, SearchColumns, SortColumns } from '../../types';
|
||||
|
||||
const ModalList = styled.div`
|
||||
.pf-c-data-toolbar__content {
|
||||
.pf-c-toolbar__content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -97,51 +97,27 @@ exports[`<ToolbarDeleteButton /> should render button 1`] = `
|
||||
zIndex={9999}
|
||||
>
|
||||
<div>
|
||||
<Component
|
||||
<Button
|
||||
aria-label="Delete"
|
||||
isDisabled={true}
|
||||
onClick={[Function]}
|
||||
variant="danger"
|
||||
>
|
||||
<ComponentWithOuia
|
||||
component={[Function]}
|
||||
componentProps={
|
||||
Object {
|
||||
"aria-label": "Delete",
|
||||
"children": "Delete",
|
||||
"isDisabled": true,
|
||||
"onClick": [Function],
|
||||
"variant": "danger",
|
||||
}
|
||||
}
|
||||
consumerContext={null}
|
||||
<button
|
||||
aria-disabled={null}
|
||||
aria-label="Delete"
|
||||
className="pf-c-button pf-m-danger"
|
||||
data-ouia-component-id={null}
|
||||
data-ouia-component-type="PF4/Button"
|
||||
data-ouia-safe={true}
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
tabIndex={null}
|
||||
type="button"
|
||||
>
|
||||
<Button
|
||||
aria-label="Delete"
|
||||
isDisabled={true}
|
||||
onClick={[Function]}
|
||||
ouiaContext={
|
||||
Object {
|
||||
"isOuia": false,
|
||||
"ouiaId": null,
|
||||
}
|
||||
}
|
||||
variant="danger"
|
||||
>
|
||||
<button
|
||||
aria-disabled={null}
|
||||
aria-label="Delete"
|
||||
className="pf-c-button pf-m-danger"
|
||||
disabled={true}
|
||||
onClick={[Function]}
|
||||
tabIndex={null}
|
||||
type="button"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</Button>
|
||||
</ComponentWithOuia>
|
||||
</Component>
|
||||
Delete
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
<Portal
|
||||
containerInfo={
|
||||
|
||||
@ -117,7 +117,7 @@ describe('<ResourceAccessList />', () => {
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
|
||||
const button = wrapper.find('ChipButton').at(0);
|
||||
const button = wrapper.find('Chip Button').at(0);
|
||||
button.prop('onClick')();
|
||||
wrapper.update();
|
||||
|
||||
@ -136,7 +136,7 @@ describe('<ResourceAccessList />', () => {
|
||||
);
|
||||
await sleep(0);
|
||||
wrapper.update();
|
||||
const button = wrapper.find('ChipButton').at(0);
|
||||
const button = wrapper.find('Chip Button').at(0);
|
||||
button.prop('onClick')();
|
||||
wrapper.update();
|
||||
|
||||
@ -155,7 +155,7 @@ describe('<ResourceAccessList />', () => {
|
||||
);
|
||||
const button = await waitForElement(
|
||||
wrapper,
|
||||
'ChipButton',
|
||||
'Chip Button',
|
||||
el => el.length === 2
|
||||
);
|
||||
button.at(0).prop('onClick')();
|
||||
@ -188,7 +188,7 @@ describe('<ResourceAccessList />', () => {
|
||||
);
|
||||
const button = await waitForElement(
|
||||
wrapper,
|
||||
'ChipButton',
|
||||
'Chip Button',
|
||||
el => el.length === 2
|
||||
);
|
||||
button.at(1).prop('onClick')();
|
||||
|
||||
@ -59,10 +59,10 @@ class ResourceAccessListItem extends React.Component {
|
||||
return (
|
||||
<Chip
|
||||
key={role.id}
|
||||
isReadOnly={!role.user_capabilities.unattach}
|
||||
onClick={() => {
|
||||
onRoleDelete(role, accessRecord);
|
||||
}}
|
||||
isReadOnly={!role.user_capabilities.unattach}
|
||||
>
|
||||
{role.name}
|
||||
</Chip>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -92,12 +92,17 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
numChips={5}
|
||||
totalChips={1}
|
||||
>
|
||||
<Unknown
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
</Unknown>
|
||||
</Chip>
|
||||
</WithI18n>
|
||||
}
|
||||
/>
|
||||
@ -151,12 +156,17 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
numChips={5}
|
||||
totalChips={1}
|
||||
>
|
||||
<Unknown
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
</Unknown>
|
||||
</Chip>
|
||||
</WithI18n>
|
||||
}
|
||||
/>
|
||||
@ -233,12 +243,17 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
numChips={5}
|
||||
totalChips={1}
|
||||
>
|
||||
<Unknown
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
</Unknown>
|
||||
</Chip>
|
||||
</WithI18n>
|
||||
}
|
||||
/>
|
||||
@ -661,12 +676,17 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
numChips={5}
|
||||
totalChips={1}
|
||||
>
|
||||
<Unknown
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
onClick={[Function]}
|
||||
tooltipPosition="top"
|
||||
>
|
||||
Member
|
||||
</Unknown>
|
||||
</Chip>
|
||||
</WithI18n>
|
||||
}
|
||||
>
|
||||
@ -801,175 +821,113 @@ exports[`<ResourceAccessListItem /> initially renders succesfully 1`] = `
|
||||
totalChips={1}
|
||||
>
|
||||
<ChipGroup
|
||||
className=""
|
||||
aria-label="Chip group category"
|
||||
categoryName=""
|
||||
closeBtnAriaLabel="Close chip group"
|
||||
collapsedText="-4 more"
|
||||
defaultIsOpen={false}
|
||||
expandedText="Show less"
|
||||
isClosable={false}
|
||||
numChips={5}
|
||||
withToolbar={false}
|
||||
onClick={[Function]}
|
||||
tooltipPosition="top"
|
||||
>
|
||||
<ul
|
||||
className="pf-c-chip-group"
|
||||
<GenerateId
|
||||
prefix="pf-random-id-"
|
||||
>
|
||||
<InnerChipGroup
|
||||
className=""
|
||||
collapsedText="-4 more"
|
||||
defaultIsOpen={false}
|
||||
expandedText="Show less"
|
||||
isOpen={false}
|
||||
numChips={5}
|
||||
onToggleCollapse={[Function]}
|
||||
withToolbar={false}
|
||||
<div
|
||||
className="pf-c-chip-group"
|
||||
>
|
||||
<Component
|
||||
component="li"
|
||||
isReadOnly={false}
|
||||
key=".$3"
|
||||
onClick={[Function]}
|
||||
<ul
|
||||
aria-label="Chip group category"
|
||||
className="pf-c-chip-group__list"
|
||||
role="list"
|
||||
>
|
||||
<ComponentWithOuia
|
||||
component={[Function]}
|
||||
componentProps={
|
||||
Object {
|
||||
"children": "Member",
|
||||
"component": "li",
|
||||
"isReadOnly": false,
|
||||
"onClick": [Function],
|
||||
}
|
||||
}
|
||||
consumerContext={null}
|
||||
<li
|
||||
className="pf-c-chip-group__list-item"
|
||||
key="0"
|
||||
>
|
||||
<Chip
|
||||
className=""
|
||||
closeBtnAriaLabel="close"
|
||||
component="li"
|
||||
component="div"
|
||||
isOverflowChip={false}
|
||||
isReadOnly={false}
|
||||
key=".$3"
|
||||
onClick={[Function]}
|
||||
ouiaContext={
|
||||
Object {
|
||||
"isOuia": false,
|
||||
"ouiaId": null,
|
||||
}
|
||||
}
|
||||
tooltipPosition="top"
|
||||
>
|
||||
<GenerateId
|
||||
prefix="pf-random-id-"
|
||||
>
|
||||
<li
|
||||
<div
|
||||
className="pf-c-chip"
|
||||
data-ouia-component-id={1}
|
||||
data-ouia-component-type="PF4/Chip"
|
||||
data-ouia-safe={true}
|
||||
>
|
||||
<span
|
||||
className="pf-c-chip__text"
|
||||
id="pf-random-id-0"
|
||||
id="pf-random-id-1"
|
||||
>
|
||||
Member
|
||||
</span>
|
||||
<ChipButton
|
||||
aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
|
||||
ariaLabel="close"
|
||||
id="remove_pf-random-id-0"
|
||||
<Button
|
||||
aria-label="close"
|
||||
aria-labelledby="remove_pf-random-id-1 pf-random-id-1"
|
||||
id="remove_pf-random-id-1"
|
||||
onClick={[Function]}
|
||||
variant="plain"
|
||||
>
|
||||
<Component
|
||||
<button
|
||||
aria-disabled={null}
|
||||
aria-label="close"
|
||||
aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
|
||||
className=""
|
||||
id="remove_pf-random-id-0"
|
||||
aria-labelledby="remove_pf-random-id-1 pf-random-id-1"
|
||||
className="pf-c-button pf-m-plain"
|
||||
data-ouia-component-id={null}
|
||||
data-ouia-component-type="PF4/Button"
|
||||
data-ouia-safe={true}
|
||||
disabled={false}
|
||||
id="remove_pf-random-id-1"
|
||||
onClick={[Function]}
|
||||
variant="plain"
|
||||
tabIndex={null}
|
||||
type="button"
|
||||
>
|
||||
<ComponentWithOuia
|
||||
component={[Function]}
|
||||
componentProps={
|
||||
Object {
|
||||
"aria-label": "close",
|
||||
"aria-labelledby": "remove_pf-random-id-0 pf-random-id-0",
|
||||
"children": <TimesCircleIcon
|
||||
aria-hidden="true"
|
||||
color="currentColor"
|
||||
noVerticalAlign={false}
|
||||
size="sm"
|
||||
title={null}
|
||||
/>,
|
||||
"className": "",
|
||||
"id": "remove_pf-random-id-0",
|
||||
"onClick": [Function],
|
||||
"variant": "plain",
|
||||
}
|
||||
}
|
||||
consumerContext={
|
||||
Object {
|
||||
"isOuia": false,
|
||||
"ouiaId": null,
|
||||
}
|
||||
}
|
||||
<TimesIcon
|
||||
aria-hidden="true"
|
||||
color="currentColor"
|
||||
noVerticalAlign={false}
|
||||
size="sm"
|
||||
>
|
||||
<Button
|
||||
aria-label="close"
|
||||
aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
|
||||
className=""
|
||||
id="remove_pf-random-id-0"
|
||||
onClick={[Function]}
|
||||
ouiaContext={
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-labelledby={null}
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
style={
|
||||
Object {
|
||||
"isOuia": false,
|
||||
"ouiaId": null,
|
||||
"verticalAlign": "-0.125em",
|
||||
}
|
||||
}
|
||||
variant="plain"
|
||||
viewBox="0 0 352 512"
|
||||
width="1em"
|
||||
>
|
||||
<button
|
||||
aria-disabled={null}
|
||||
aria-label="close"
|
||||
aria-labelledby="remove_pf-random-id-0 pf-random-id-0"
|
||||
className="pf-c-button pf-m-plain"
|
||||
disabled={false}
|
||||
id="remove_pf-random-id-0"
|
||||
onClick={[Function]}
|
||||
tabIndex={null}
|
||||
type="button"
|
||||
>
|
||||
<TimesCircleIcon
|
||||
aria-hidden="true"
|
||||
color="currentColor"
|
||||
noVerticalAlign={false}
|
||||
size="sm"
|
||||
title={null}
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
aria-labelledby={null}
|
||||
fill="currentColor"
|
||||
height="1em"
|
||||
role="img"
|
||||
style={
|
||||
Object {
|
||||
"verticalAlign": "-0.125em",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 512 512"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"
|
||||
transform=""
|
||||
/>
|
||||
</svg>
|
||||
</TimesCircleIcon>
|
||||
</button>
|
||||
</Button>
|
||||
</ComponentWithOuia>
|
||||
</Component>
|
||||
</ChipButton>
|
||||
</li>
|
||||
<path
|
||||
d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"
|
||||
transform=""
|
||||
/>
|
||||
</svg>
|
||||
</TimesIcon>
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</GenerateId>
|
||||
</Chip>
|
||||
</ComponentWithOuia>
|
||||
</Component>
|
||||
</InnerChipGroup>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</GenerateId>
|
||||
</ChipGroup>
|
||||
</ChipGroup>
|
||||
</I18n>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { shape, string, number, arrayOf, node, oneOfType } from 'prop-types';
|
||||
import { Tab, Tabs } from '@patternfly/react-core';
|
||||
import { Tab, Tabs, TabTitleText } from '@patternfly/react-core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
function RoutedTabs(props) {
|
||||
@ -36,7 +36,7 @@ function RoutedTabs(props) {
|
||||
eventKey={tab.id}
|
||||
key={tab.id}
|
||||
link={tab.link}
|
||||
title={tab.name}
|
||||
title={<TabTitleText>{tab.name}</TabTitleText>}
|
||||
/>
|
||||
))}
|
||||
</Tabs>
|
||||
|
||||
@ -10,13 +10,10 @@ import {
|
||||
useLocation,
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
import { CardActions } from '@patternfly/react-core';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import CardCloseButton from '../CardCloseButton';
|
||||
import RoutedTabs from '../RoutedTabs';
|
||||
import ContentError from '../ContentError';
|
||||
import ContentLoading from '../ContentLoading';
|
||||
import { TabbedCardHeader } from '../Card';
|
||||
import ScheduleDetail from './ScheduleDetail';
|
||||
import ScheduleEdit from './ScheduleEdit';
|
||||
import { SchedulesAPI } from '../../api';
|
||||
@ -90,23 +87,17 @@ function Schedule({ i18n, setBreadcrumb, unifiedJobTemplate }) {
|
||||
return <ContentError error={contentError} />;
|
||||
}
|
||||
|
||||
let cardHeader = null;
|
||||
let showCardHeader = true;
|
||||
|
||||
if (
|
||||
location.pathname.includes('schedules/') &&
|
||||
!location.pathname.endsWith('edit')
|
||||
!location.pathname.includes('schedules/') ||
|
||||
location.pathname.endsWith('edit')
|
||||
) {
|
||||
cardHeader = (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo={`${pathRoot}schedules`} />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
showCardHeader = false;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{cardHeader}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from={`${pathRoot}schedules/:scheduleId`}
|
||||
|
||||
@ -24,6 +24,7 @@ import ChipGroup from '../../ChipGroup';
|
||||
|
||||
const PromptTitle = styled(Title)`
|
||||
--pf-c-title--m-md--FontWeight: 700;
|
||||
grid-column: 1 / -1;
|
||||
`;
|
||||
|
||||
function ScheduleDetail({ schedule, i18n }) {
|
||||
@ -140,7 +141,7 @@ function ScheduleDetail({ schedule, i18n }) {
|
||||
/>
|
||||
{showPromptedFields && (
|
||||
<>
|
||||
<PromptTitle size="md" css="grid-column: 1 / -1;">
|
||||
<PromptTitle headingLevel="h2">
|
||||
{i18n._(t`Prompted Fields`)}
|
||||
</PromptTitle>
|
||||
<Detail label={i18n._(t`Job Type`)} value={job_type} />
|
||||
|
||||
@ -136,7 +136,7 @@ describe('<ScheduleDetail />', () => {
|
||||
expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(0);
|
||||
});
|
||||
test('details should render with the proper values with prompts', async () => {
|
||||
SchedulesAPI.readCredentials.mockResolvedValueOnce({
|
||||
SchedulesAPI.readCredentials.mockResolvedValue({
|
||||
data: {
|
||||
count: 2,
|
||||
results: [
|
||||
@ -182,6 +182,7 @@ describe('<ScheduleDetail />', () => {
|
||||
);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
// await waitForElement(wrapper, 'Title', el => el.length > 0);
|
||||
expect(
|
||||
wrapper
|
||||
.find('Detail[label="Name"]')
|
||||
|
||||
@ -36,7 +36,7 @@ function ScheduleOccurrences({ preview = { local: [], utc: [] }, i18n }) {
|
||||
fullWidth
|
||||
css="grid-column: 1 / -1"
|
||||
>
|
||||
<Split gutter="sm">
|
||||
<Split hasGutter>
|
||||
<SplitItem>
|
||||
<OccurrencesLabel>
|
||||
<span>{i18n._(t`Occurrences`)}</span>
|
||||
|
||||
@ -231,7 +231,9 @@ const FrequencyDetailSubform = ({ i18n }) => {
|
||||
fieldId="schedule-run-every"
|
||||
helperTextInvalid={intervalMeta.error}
|
||||
isRequired
|
||||
isValid={!intervalMeta.touched || !intervalMeta.error}
|
||||
validated={
|
||||
!intervalMeta.touched || !intervalMeta.error ? 'default' : 'error'
|
||||
}
|
||||
label={i18n._(t`Run every`)}
|
||||
>
|
||||
<div css="display: flex">
|
||||
@ -255,7 +257,11 @@ const FrequencyDetailSubform = ({ i18n }) => {
|
||||
fieldId="schedule-days-of-week"
|
||||
helperTextInvalid={daysOfWeekMeta.error}
|
||||
isRequired
|
||||
isValid={!daysOfWeekMeta.touched || !daysOfWeekMeta.error}
|
||||
validated={
|
||||
!daysOfWeekMeta.touched || !daysOfWeekMeta.error
|
||||
? 'default'
|
||||
: 'error'
|
||||
}
|
||||
label={i18n._(t`On days`)}
|
||||
>
|
||||
<div css="display: flex">
|
||||
@ -339,7 +345,9 @@ const FrequencyDetailSubform = ({ i18n }) => {
|
||||
fieldId="schedule-run-on"
|
||||
helperTextInvalid={runOnMeta.error}
|
||||
isRequired
|
||||
isValid={!runOnMeta.touched || !runOnMeta.error}
|
||||
validated={
|
||||
!runOnMeta.touched || !runOnMeta.error ? 'default' : 'error'
|
||||
}
|
||||
label={i18n._(t`Run on`)}
|
||||
>
|
||||
<RunOnRadio
|
||||
@ -502,7 +510,7 @@ const FrequencyDetailSubform = ({ i18n }) => {
|
||||
fieldId="schedule-end"
|
||||
helperTextInvalid={endMeta.error}
|
||||
isRequired
|
||||
isValid={!endMeta.touched || !endMeta.error}
|
||||
validated={!endMeta.touched || !endMeta.error ? 'default' : 'error'}
|
||||
label={i18n._(t`End`)}
|
||||
>
|
||||
<Radio
|
||||
@ -556,7 +564,11 @@ const FrequencyDetailSubform = ({ i18n }) => {
|
||||
fieldId="schedule-end-datetime"
|
||||
helperTextInvalid={endDateTimeMeta.error}
|
||||
isRequired
|
||||
isValid={!endDateTimeMeta.touched || !endDateTimeMeta.error}
|
||||
validated={
|
||||
!endDateTimeMeta.touched || !endDateTimeMeta.error
|
||||
? 'default'
|
||||
: 'error'
|
||||
}
|
||||
label={i18n._(t`End date/time`)}
|
||||
>
|
||||
<input
|
||||
|
||||
@ -104,7 +104,11 @@ function ScheduleFormFields({ i18n, zoneOptions }) {
|
||||
fieldId="schedule-start-datetime"
|
||||
helperTextInvalid={startDateTimeMeta.error}
|
||||
isRequired
|
||||
isValid={!startDateTimeMeta.touched || !startDateTimeMeta.error}
|
||||
validated={
|
||||
!startDateTimeMeta.touched || !startDateTimeMeta.error
|
||||
? 'default'
|
||||
: 'error'
|
||||
}
|
||||
label={i18n._(t`Start date/time`)}
|
||||
>
|
||||
<input
|
||||
@ -120,7 +124,9 @@ function ScheduleFormFields({ i18n, zoneOptions }) {
|
||||
fieldId="schedule-timezone"
|
||||
helperTextInvalid={timezoneMeta.error}
|
||||
isRequired
|
||||
isValid={!timezoneMeta.touched || !timezoneMeta.error}
|
||||
validated={
|
||||
!timezoneMeta.touched || !timezoneMeta.error ? 'default' : 'error'
|
||||
}
|
||||
label={i18n._(t`Local time zone`)}
|
||||
>
|
||||
<AnsibleSelect
|
||||
@ -134,7 +140,9 @@ function ScheduleFormFields({ i18n, zoneOptions }) {
|
||||
fieldId="schedule-requency"
|
||||
helperTextInvalid={frequencyMeta.error}
|
||||
isRequired
|
||||
isValid={!frequencyMeta.touched || !frequencyMeta.error}
|
||||
validated={
|
||||
!frequencyMeta.touched || !frequencyMeta.error ? 'default' : 'error'
|
||||
}
|
||||
label={i18n._(t`Run frequency`)}
|
||||
>
|
||||
<AnsibleSelect
|
||||
@ -153,7 +161,9 @@ function ScheduleFormFields({ i18n, zoneOptions }) {
|
||||
</FormGroup>
|
||||
{frequency.value !== 'none' && (
|
||||
<SubFormLayout>
|
||||
<Title size="md">{i18n._(t`Frequency Details`)}</Title>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{i18n._(t`Frequency Details`)}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
<FrequencyDetailSubform />
|
||||
</FormColumnLayout>
|
||||
|
||||
@ -16,12 +16,10 @@ import {
|
||||
SelectOption,
|
||||
SelectVariant,
|
||||
TextInput,
|
||||
ToolbarGroup,
|
||||
ToolbarItem,
|
||||
ToolbarFilter,
|
||||
} from '@patternfly/react-core';
|
||||
import {
|
||||
DataToolbarGroup,
|
||||
DataToolbarItem,
|
||||
DataToolbarFilter,
|
||||
} from '@patternfly/react-core/dist/umd/experimental';
|
||||
import { SearchIcon } from '@patternfly/react-icons';
|
||||
import styled from 'styled-components';
|
||||
import { parseQueryString } from '../../util/qs';
|
||||
@ -205,8 +203,8 @@ class Search extends React.Component {
|
||||
const chipsByKey = getChipsByKey();
|
||||
|
||||
return (
|
||||
<DataToolbarGroup variant="filter-group">
|
||||
<DataToolbarItem>
|
||||
<ToolbarGroup variant="filter-group">
|
||||
<ToolbarItem>
|
||||
{searchDropdownItems.length > 0 ? (
|
||||
<Dropdown
|
||||
onToggle={this.handleDropdownToggle}
|
||||
@ -227,10 +225,10 @@ class Search extends React.Component {
|
||||
) : (
|
||||
<NoOptionDropdown>{searchColumnName}</NoOptionDropdown>
|
||||
)}
|
||||
</DataToolbarItem>
|
||||
</ToolbarItem>
|
||||
{columns.map(
|
||||
({ key, name, options, isBoolean, booleanLabels = {} }) => (
|
||||
<DataToolbarFilter
|
||||
<ToolbarFilter
|
||||
chips={chipsByKey[key] ? chipsByKey[key].chips : []}
|
||||
deleteChip={(unusedKey, chip) => {
|
||||
const [columnKey, ...value] = chip.key.split(':');
|
||||
@ -253,7 +251,7 @@ class Search extends React.Component {
|
||||
const [, ...value] = chip.key.split(':');
|
||||
return value.join(':');
|
||||
})}
|
||||
isExpanded={isFilterDropdownOpen}
|
||||
isOpen={isFilterDropdownOpen}
|
||||
placeholderText={`Filter By ${name}`}
|
||||
>
|
||||
{options.map(([optionKey, optionLabel]) => (
|
||||
@ -272,7 +270,7 @@ class Search extends React.Component {
|
||||
this.handleFilterBooleanSelect(key, selection)
|
||||
}
|
||||
selections={chipsByKey[key].chips[0]}
|
||||
isExpanded={isFilterDropdownOpen}
|
||||
isOpen={isFilterDropdownOpen}
|
||||
placeholderText={`Filter By ${name}`}
|
||||
>
|
||||
<SelectOption key="true" value="true">
|
||||
@ -311,10 +309,10 @@ class Search extends React.Component {
|
||||
</div>
|
||||
</InputGroup>
|
||||
)}
|
||||
</DataToolbarFilter>
|
||||
</ToolbarFilter>
|
||||
)
|
||||
)}
|
||||
</DataToolbarGroup>
|
||||
</ToolbarGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,5 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
DataToolbar,
|
||||
DataToolbarContent,
|
||||
} from '@patternfly/react-core/dist/umd/experimental';
|
||||
import { Toolbar, ToolbarContent } from '@patternfly/react-core';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mountWithContexts } from '../../../testUtils/enzymeHelpers';
|
||||
@ -33,15 +30,15 @@ describe('<Search />', () => {
|
||||
const onSearch = jest.fn();
|
||||
|
||||
search = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
);
|
||||
|
||||
search.find(searchTextInput).instance().value = 'test-321';
|
||||
@ -56,15 +53,15 @@ describe('<Search />', () => {
|
||||
const columns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
).find('Search');
|
||||
expect(wrapper.state('isSearchDropdownOpen')).toEqual(false);
|
||||
wrapper.instance().handleDropdownToggle(true);
|
||||
@ -78,15 +75,15 @@ describe('<Search />', () => {
|
||||
];
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
).find('Search');
|
||||
expect(wrapper.state('searchKey')).toEqual('name');
|
||||
wrapper
|
||||
@ -101,15 +98,15 @@ describe('<Search />', () => {
|
||||
const columns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
);
|
||||
|
||||
wrapper.find(searchTextInput).instance().value = '';
|
||||
@ -125,15 +122,15 @@ describe('<Search />', () => {
|
||||
const columns = [{ name: 'Name', key: 'name', isDefault: true }];
|
||||
const onSearch = jest.fn();
|
||||
const wrapper = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search qsConfig={QS_CONFIG} columns={columns} onSearch={onSearch} />
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
);
|
||||
|
||||
wrapper.find(searchTextInput).instance().value = 'test-321';
|
||||
@ -156,23 +153,23 @@ describe('<Search />', () => {
|
||||
initialEntries: [`/organizations/${query}`],
|
||||
});
|
||||
const wrapper = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${QS_CONFIG.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search qsConfig={QS_CONFIG} columns={columns} />
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>,
|
||||
</ToolbarContent>
|
||||
</Toolbar>,
|
||||
{ context: { router: { history } } }
|
||||
);
|
||||
const typeFilterWrapper = wrapper.find(
|
||||
'DataToolbarFilter[categoryName="Type"]'
|
||||
'ToolbarFilter[categoryName="Type"]'
|
||||
);
|
||||
expect(typeFilterWrapper.prop('chips')[0].key).toEqual('or__type:foo');
|
||||
const nameFilterWrapper = wrapper.find(
|
||||
'DataToolbarFilter[categoryName="Name"]'
|
||||
'ToolbarFilter[categoryName="Name"]'
|
||||
);
|
||||
expect(nameFilterWrapper.prop('chips')[0].key).toEqual('name:bar');
|
||||
});
|
||||
@ -197,19 +194,19 @@ describe('<Search />', () => {
|
||||
});
|
||||
const onRemove = jest.fn();
|
||||
const wrapper = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${qsConfigNew.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search
|
||||
qsConfig={qsConfigNew}
|
||||
columns={columns}
|
||||
onRemove={onRemove}
|
||||
/>
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>,
|
||||
</ToolbarContent>
|
||||
</Toolbar>,
|
||||
{ context: { router: { history } } }
|
||||
);
|
||||
expect(history.location.search).toEqual(query);
|
||||
@ -243,19 +240,19 @@ describe('<Search />', () => {
|
||||
});
|
||||
const onRemove = jest.fn();
|
||||
const wrapper = mountWithContexts(
|
||||
<DataToolbar
|
||||
<Toolbar
|
||||
id={`${qsConfigNew.namespace}-list-toolbar`}
|
||||
clearAllFilters={() => {}}
|
||||
collapseListedFiltersBreakpoint="md"
|
||||
collapseListedFiltersBreakpoint="lg"
|
||||
>
|
||||
<DataToolbarContent>
|
||||
<ToolbarContent>
|
||||
<Search
|
||||
qsConfig={qsConfigNew}
|
||||
columns={columns}
|
||||
onRemove={onRemove}
|
||||
/>
|
||||
</DataToolbarContent>
|
||||
</DataToolbar>,
|
||||
</ToolbarContent>
|
||||
</Toolbar>,
|
||||
{ context: { router: { history } } }
|
||||
);
|
||||
expect(history.location.search).toEqual(query);
|
||||
|
||||
@ -56,6 +56,7 @@ describe('<UserAndTeamAccessAdd/>', () => {
|
||||
/>
|
||||
);
|
||||
});
|
||||
await waitForElement(wrapper, 'PFWizard');
|
||||
});
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
@ -68,12 +69,12 @@ describe('<UserAndTeamAccessAdd/>', () => {
|
||||
expect(wrapper.find('Button[type="submit"]').prop('isDisabled')).toBe(true);
|
||||
expect(
|
||||
wrapper
|
||||
.find('WizardNavItem[text="Select items from list"]')
|
||||
.find('WizardNavItem[content="Select items from list"]')
|
||||
.prop('isDisabled')
|
||||
).toBe(true);
|
||||
expect(
|
||||
wrapper
|
||||
.find('WizardNavItem[text="Select roles to apply"]')
|
||||
.find('WizardNavItem[content="Select roles to apply"]')
|
||||
.prop('isDisabled')
|
||||
).toBe(true);
|
||||
await act(async () =>
|
||||
@ -89,17 +90,19 @@ describe('<UserAndTeamAccessAdd/>', () => {
|
||||
wrapper.find('Button[type="submit"]').prop('onClick')()
|
||||
);
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper.find('WizardNavItem[text="Add resource type"]').prop('isDisabled')
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper
|
||||
.find('WizardNavItem[text="Select items from list"]')
|
||||
.find('WizardNavItem[content="Add resource type"]')
|
||||
.prop('isDisabled')
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper
|
||||
.find('WizardNavItem[text="Select roles to apply"]')
|
||||
.find('WizardNavItem[content="Select items from list"]')
|
||||
.prop('isDisabled')
|
||||
).toBe(false);
|
||||
expect(
|
||||
wrapper
|
||||
.find('WizardNavItem[content="Select roles to apply"]')
|
||||
.prop('isDisabled')
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
@ -3,7 +3,7 @@ import styled from 'styled-components';
|
||||
|
||||
Wizard.displayName = 'PFWizard';
|
||||
export default styled(Wizard)`
|
||||
.pf-c-data-toolbar__content {
|
||||
.pf-c-toolbar__content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -91,8 +91,8 @@ describe('<ApplicationAdd/>', () => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
||||
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
||||
expect(wrapper.find('InnerChipGroup').length).toBe(1);
|
||||
expect(wrapper.find('InnerChipGroup').text()).toBe('organization');
|
||||
expect(wrapper.find('Chip').length).toBe(1);
|
||||
expect(wrapper.find('Chip').text()).toBe('organization');
|
||||
expect(
|
||||
wrapper
|
||||
.find('AnsibleSelect[name="authorization_grant_type"]')
|
||||
|
||||
@ -107,8 +107,8 @@ describe('<ApplicationForm', () => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('input#name').prop('value')).toBe('new foo');
|
||||
expect(wrapper.find('input#description').prop('value')).toBe('new bar');
|
||||
expect(wrapper.find('InnerChipGroup').length).toBe(1);
|
||||
expect(wrapper.find('InnerChipGroup').text()).toBe('organization');
|
||||
expect(wrapper.find('Chip').length).toBe(1);
|
||||
expect(wrapper.find('Chip').text()).toBe('organization');
|
||||
expect(
|
||||
wrapper
|
||||
.find('AnsibleSelect[name="authorization_grant_type"]')
|
||||
|
||||
@ -15,7 +15,9 @@ class AuthSettings extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`Authentication Settings`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`Authentication Settings`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { Card, PageSection, CardActions } from '@patternfly/react-core';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import {
|
||||
Switch,
|
||||
useParams,
|
||||
@ -11,8 +12,6 @@ import {
|
||||
Redirect,
|
||||
Link,
|
||||
} from 'react-router-dom';
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import { ResourceAccessList } from '../../components/ResourceAccessList';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
@ -46,6 +45,16 @@ function Credential({ i18n, setBreadcrumb }) {
|
||||
}, [id, pathname, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Credentials`)}
|
||||
</>
|
||||
),
|
||||
link: `/credentials`,
|
||||
id: 99,
|
||||
},
|
||||
{ name: i18n._(t`Details`), link: `/credentials/${id}/details`, id: 0 },
|
||||
];
|
||||
|
||||
@ -57,17 +66,10 @@ function Credential({ i18n, setBreadcrumb }) {
|
||||
});
|
||||
}
|
||||
|
||||
let cardHeader = hasContentLoading ? null : (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/credentials" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
let showCardHeader = true;
|
||||
|
||||
if (pathname.endsWith('edit') || pathname.endsWith('add')) {
|
||||
cardHeader = null;
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
if (!hasContentLoading && contentError) {
|
||||
@ -90,7 +92,7 @@ function Credential({ i18n, setBreadcrumb }) {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{cardHeader}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/credentials/:id"
|
||||
|
||||
@ -31,7 +31,7 @@ describe('<Credential />', () => {
|
||||
wrapper = mountWithContexts(<Credential setBreadcrumb={() => {}} />);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 1);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 2);
|
||||
});
|
||||
|
||||
test('initially renders org-based credential succesfully', async () => {
|
||||
@ -44,7 +44,7 @@ describe('<Credential />', () => {
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
// org-based credential detail needs access tab
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 2);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 3);
|
||||
});
|
||||
|
||||
test('should show content error when user attempts to navigate to erroneous route', async () => {
|
||||
|
||||
@ -104,7 +104,9 @@ function CredentialFormFields({
|
||||
fieldId="credential-credentialType"
|
||||
helperTextInvalid={credTypeMeta.error}
|
||||
isRequired
|
||||
isValid={!credTypeMeta.touched || !credTypeMeta.error}
|
||||
validated={
|
||||
!credTypeMeta.touched || !credTypeMeta.error ? 'default' : 'error'
|
||||
}
|
||||
label={i18n._(t`Credential Type`)}
|
||||
>
|
||||
<AnsibleSelect
|
||||
|
||||
@ -191,6 +191,12 @@ describe('<CredentialForm />', () => {
|
||||
).toBe('');
|
||||
});
|
||||
test('should show error when error thrown parsing JSON', async () => {
|
||||
await act(async () => {
|
||||
await wrapper
|
||||
.find('AnsibleSelect[id="credential_type"]')
|
||||
.invoke('onChange')(null, 10);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('#credential-gce-file-helper').text()).toBe(
|
||||
'Select a JSON formatted service account key to autopopulate the following fields.'
|
||||
);
|
||||
@ -201,7 +207,15 @@ describe('<CredentialForm />', () => {
|
||||
});
|
||||
});
|
||||
wrapper.update();
|
||||
expect(wrapper.find('#credential-gce-file-helper').text()).toBe(
|
||||
expect(
|
||||
wrapper.find('FormGroup[fieldId="credential-gce-file"]').prop('isValid')
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('FormGroup[fieldId="credential-gce-file"]')
|
||||
.prop('helperTextInvalid')
|
||||
).toBe(
|
||||
'There was an error parsing the file. Please check the file formatting and try again.'
|
||||
);
|
||||
});
|
||||
|
||||
@ -21,7 +21,9 @@ function TypeInputsSubForm({ credentialType, i18n }) {
|
||||
);
|
||||
return (
|
||||
<SubFormLayout>
|
||||
<Title size="md">{i18n._(t`Type Details`)}</Title>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{i18n._(t`Type Details`)}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
{credentialType.namespace === 'gce' && <GceFileUploadField />}
|
||||
{stringFields.map(fieldOptions =>
|
||||
|
||||
@ -15,7 +15,9 @@ class Dashboard extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`Dashboard`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`Dashboard`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -9,10 +9,8 @@ import {
|
||||
useRouteMatch,
|
||||
useLocation,
|
||||
} from 'react-router-dom';
|
||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import ContentLoading from '../../components/ContentLoading';
|
||||
@ -47,6 +45,16 @@ function Host({ i18n, setBreadcrumb }) {
|
||||
}, [match.params.id, location, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Hosts`)}
|
||||
</>
|
||||
),
|
||||
link: `/hosts`,
|
||||
id: 99,
|
||||
},
|
||||
{
|
||||
name: i18n._(t`Details`),
|
||||
link: `${match.url}/details`,
|
||||
@ -96,17 +104,16 @@ function Host({ i18n, setBreadcrumb }) {
|
||||
);
|
||||
}
|
||||
|
||||
let showCardHeader = true;
|
||||
|
||||
if (location.pathname.endsWith('edit')) {
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{location.pathname.endsWith('edit') ? null : (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/hosts" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
)}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect from="/hosts/:id" to="/hosts/:id/details" exact />
|
||||
{host && [
|
||||
|
||||
@ -15,7 +15,9 @@ class InstanceGroups extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`Instance Groups`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`Instance Groups`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -9,10 +9,8 @@ import {
|
||||
useLocation,
|
||||
useRouteMatch,
|
||||
} from 'react-router-dom';
|
||||
|
||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import ContentLoading from '../../components/ContentLoading';
|
||||
import JobList from '../../components/JobList';
|
||||
@ -51,6 +49,16 @@ function Inventory({ i18n, setBreadcrumb }) {
|
||||
}, [match.params.id, location.pathname, setBreadcrumb]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Inventories`)}
|
||||
</>
|
||||
),
|
||||
link: `/inventories`,
|
||||
id: 99,
|
||||
},
|
||||
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
|
||||
{ name: i18n._(t`Access`), link: `${match.url}/access`, id: 1 },
|
||||
{ name: i18n._(t`Groups`), link: `${match.url}/groups`, id: 2 },
|
||||
@ -90,19 +98,20 @@ function Inventory({ i18n, setBreadcrumb }) {
|
||||
);
|
||||
}
|
||||
|
||||
let showCardHeader = true;
|
||||
|
||||
if (
|
||||
['edit', 'add', 'groups/', 'hosts/', 'sources/'].some(name =>
|
||||
location.pathname.includes(name)
|
||||
)
|
||||
) {
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{['edit', 'add', 'groups/', 'hosts/', 'sources/'].some(name =>
|
||||
location.pathname.includes(name)
|
||||
) ? null : (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/inventories" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
)}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/inventories/inventory/:id"
|
||||
|
||||
@ -30,7 +30,7 @@ describe('<Inventory />', () => {
|
||||
wrapper = mountWithContexts(<Inventory setBreadcrumb={() => {}} />);
|
||||
});
|
||||
await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 6);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 7);
|
||||
});
|
||||
|
||||
test('should show content error when user attempts to navigate to erroneous route', async () => {
|
||||
|
||||
@ -10,13 +10,10 @@ import {
|
||||
useLocation,
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
import { CardActions } from '@patternfly/react-core';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import CardCloseButton from '../../../components/CardCloseButton';
|
||||
import RoutedTabs from '../../../components/RoutedTabs';
|
||||
import ContentError from '../../../components/ContentError';
|
||||
import ContentLoading from '../../../components/ContentLoading';
|
||||
import { TabbedCardHeader } from '../../../components/Card';
|
||||
import InventoryGroupEdit from '../InventoryGroupEdit/InventoryGroupEdit';
|
||||
import InventoryGroupDetail from '../InventoryGroupDetail/InventoryGroupDetail';
|
||||
import InventoryGroupHosts from '../InventoryGroupHosts';
|
||||
@ -99,18 +96,14 @@ function InventoryGroup({ i18n, setBreadcrumb, inventory }) {
|
||||
);
|
||||
}
|
||||
|
||||
let showCardHeader = true;
|
||||
if (['add', 'edit'].some(name => location.pathname.includes(name))) {
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{['add', 'edit'].some(name => location.pathname.includes(name)) ? null : (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton
|
||||
linkTo={`/inventories/inventory/${inventory.id}/groups`}
|
||||
/>
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
)}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/inventories/inventory/:id/groups/:groupId"
|
||||
|
||||
@ -163,9 +163,7 @@ describe('<InventoryGroupsList />', () => {
|
||||
});
|
||||
wrapper.update();
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find('DataToolbar Button[aria-label="Delete"]')
|
||||
.invoke('onClick')();
|
||||
wrapper.find('Toolbar Button[aria-label="Delete"]').invoke('onClick')();
|
||||
});
|
||||
await waitForElement(
|
||||
wrapper,
|
||||
@ -197,14 +195,12 @@ describe('<InventoryGroupsList />', () => {
|
||||
});
|
||||
wrapper.update();
|
||||
await act(async () => {
|
||||
wrapper
|
||||
.find('DataToolbar Button[aria-label="Delete"]')
|
||||
.invoke('onClick')();
|
||||
wrapper.find('Toolbar Button[aria-label="Delete"]').invoke('onClick')();
|
||||
});
|
||||
await waitForElement(
|
||||
wrapper,
|
||||
'InventoryGroupsDeleteModal',
|
||||
el => el.props().isModalOpen === true
|
||||
'AlertModal[title="Delete Group?"]',
|
||||
el => el.props().isOpen === true
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper.find('Radio[id="radio-delete"]').invoke('onChange')();
|
||||
@ -215,7 +211,11 @@ describe('<InventoryGroupsList />', () => {
|
||||
.find('ModalBoxFooter Button[aria-label="Delete"]')
|
||||
.invoke('onClick')();
|
||||
});
|
||||
await waitForElement(wrapper, { title: 'Error!', variant: 'error' });
|
||||
await waitForElement(
|
||||
wrapper,
|
||||
'AlertModal[title="Error!"] Modal',
|
||||
el => el.props().isOpen === true && el.props().title === 'Error!'
|
||||
);
|
||||
await act(async () => {
|
||||
wrapper.find('ModalBoxCloseButton').invoke('onClose')();
|
||||
});
|
||||
|
||||
@ -9,13 +9,11 @@ import {
|
||||
useRouteMatch,
|
||||
useLocation,
|
||||
} from 'react-router-dom';
|
||||
import { Card, CardActions } from '@patternfly/react-core';
|
||||
import { Card } from '@patternfly/react-core';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import useRequest from '../../../util/useRequest';
|
||||
|
||||
import { InventoriesAPI } from '../../../api';
|
||||
import { TabbedCardHeader } from '../../../components/Card';
|
||||
import CardCloseButton from '../../../components/CardCloseButton';
|
||||
import ContentError from '../../../components/ContentError';
|
||||
import ContentLoading from '../../../components/ContentLoading';
|
||||
import RoutedTabs from '../../../components/RoutedTabs';
|
||||
@ -110,16 +108,14 @@ function InventoryHost({ i18n, setBreadcrumb, inventory }) {
|
||||
);
|
||||
}
|
||||
|
||||
let showCardHeader = true;
|
||||
if (['edit'].some(name => location.pathname.includes(name))) {
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{['edit'].some(name => location.pathname.includes(name)) ? null : (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo={hostListUrl} />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
)}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
|
||||
{isLoading && <ContentLoading />}
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import {
|
||||
useLocation,
|
||||
} from 'react-router-dom';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { CardActions } from '@patternfly/react-core';
|
||||
import useRequest from '../../../util/useRequest';
|
||||
|
||||
import {
|
||||
@ -18,9 +17,7 @@ import {
|
||||
InventorySourcesAPI,
|
||||
OrganizationsAPI,
|
||||
} from '../../../api';
|
||||
import { TabbedCardHeader } from '../../../components/Card';
|
||||
import { Schedules } from '../../../components/Schedule';
|
||||
import CardCloseButton from '../../../components/CardCloseButton';
|
||||
import ContentError from '../../../components/ContentError';
|
||||
import ContentLoading from '../../../components/ContentLoading';
|
||||
import RoutedTabs from '../../../components/RoutedTabs';
|
||||
@ -112,18 +109,15 @@ function InventorySource({ i18n, inventory, setBreadcrumb, me }) {
|
||||
return <ContentError error={error} />;
|
||||
}
|
||||
|
||||
let showCardHeader = true;
|
||||
|
||||
if (['edit', 'schedules/'].some(name => location.pathname.includes(name))) {
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{['edit', 'schedules/'].some(name =>
|
||||
location.pathname.includes(name)
|
||||
) ? null : (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo={sourceListUrl} />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
)}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
|
||||
{isLoading && <ContentLoading />}
|
||||
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import React, { Component } from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { Switch, Route, Redirect, withRouter, Link } from 'react-router-dom';
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import JobList from '../../components/JobList';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
@ -64,6 +63,16 @@ class SmartInventory extends Component {
|
||||
const { contentError, hasContentLoading, inventory } = this.state;
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Inventories`)}
|
||||
</>
|
||||
),
|
||||
link: `/inventories`,
|
||||
id: 99,
|
||||
},
|
||||
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
|
||||
{ name: i18n._(t`Access`), link: `${match.url}/access`, id: 1 },
|
||||
{ name: i18n._(t`Hosts`), link: `${match.url}/hosts`, id: 2 },
|
||||
@ -74,17 +83,10 @@ class SmartInventory extends Component {
|
||||
},
|
||||
];
|
||||
|
||||
let cardHeader = hasContentLoading ? null : (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/inventories" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
let showCardHeader = true;
|
||||
|
||||
if (location.pathname.endsWith('edit')) {
|
||||
cardHeader = null;
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
if (!hasContentLoading && contentError) {
|
||||
@ -108,7 +110,7 @@ class SmartInventory extends Component {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{cardHeader}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/inventories/smart_inventory/:id"
|
||||
|
||||
@ -29,7 +29,7 @@ describe('<SmartInventory />', () => {
|
||||
'SmartInventory',
|
||||
el => el.state('hasContentLoading') === false
|
||||
);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 4);
|
||||
await waitForElement(wrapper, '.pf-c-tabs__item', el => el.length === 5);
|
||||
done();
|
||||
});
|
||||
test('should show content error when user attempts to navigate to erroneous route', async () => {
|
||||
|
||||
@ -117,7 +117,9 @@ const InventorySourceFormFields = ({ sourceOptions, i18n }) => {
|
||||
fieldId="source"
|
||||
helperTextInvalid={sourceMeta.error}
|
||||
isRequired
|
||||
isValid={!sourceMeta.touched || !sourceMeta.error}
|
||||
validated={
|
||||
!sourceMeta.touched || !sourceMeta.error ? 'default' : 'error'
|
||||
}
|
||||
label={i18n._(t`Source`)}
|
||||
>
|
||||
<AnsibleSelect
|
||||
@ -161,7 +163,9 @@ const InventorySourceFormFields = ({ sourceOptions, i18n }) => {
|
||||
)}
|
||||
{sourceField.value !== '' && (
|
||||
<SubFormLayout>
|
||||
<Title size="md">{i18n._(t`Source details`)}</Title>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{i18n._(t`Source details`)}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
{
|
||||
{
|
||||
|
||||
@ -83,9 +83,11 @@ const SCMSubForm = ({ i18n }) => {
|
||||
<FormGroup
|
||||
fieldId="source_path"
|
||||
helperTextInvalid={sourcePathError?.message || sourcePathMeta.error}
|
||||
isValid={
|
||||
validated={
|
||||
(!sourcePathMeta.error || !sourcePathMeta.touched) &&
|
||||
!sourcePathError?.message
|
||||
? 'default'
|
||||
: 'error'
|
||||
}
|
||||
isRequired
|
||||
label={i18n._(t`Inventory file`)}
|
||||
|
||||
@ -229,7 +229,7 @@ export const VerbosityField = withI18n()(({ i18n }) => {
|
||||
return (
|
||||
<FormGroup
|
||||
fieldId="verbosity"
|
||||
isValid={isValid}
|
||||
validated={isValid ? 'default' : 'error'}
|
||||
label={i18n._(t`Verbosity`)}
|
||||
>
|
||||
<FieldTooltip
|
||||
|
||||
@ -15,7 +15,9 @@ class InventoryScripts extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`Inventory Scripts`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`Inventory Scripts`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -2,11 +2,10 @@ import React, { Component } from 'react';
|
||||
import { Route, withRouter, Switch, Redirect, Link } from 'react-router-dom';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import { JobsAPI } from '../../api';
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
|
||||
import JobDetail from './JobDetail';
|
||||
@ -67,21 +66,24 @@ class Job extends Component {
|
||||
}
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Jobs`)}
|
||||
</>
|
||||
),
|
||||
link: `/jobs`,
|
||||
id: 99,
|
||||
},
|
||||
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
|
||||
{ name: i18n._(t`Output`), link: `${match.url}/output`, id: 1 },
|
||||
];
|
||||
|
||||
let cardHeader = (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/jobs" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
let showCardHeader = true;
|
||||
|
||||
if (!isInitialized) {
|
||||
cardHeader = null;
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
if (!hasContentLoading && contentError) {
|
||||
@ -117,7 +119,7 @@ class Job extends Component {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{cardHeader}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/jobs/:type/:id"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal as PFModal, Tab, Tabs as PFTabs } from '@patternfly/react-core';
|
||||
import { Modal, Tab, Tabs, TabTitleText } from '@patternfly/react-core';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
@ -12,18 +12,6 @@ import CodeMirrorInput from '../../../components/CodeMirrorInput';
|
||||
|
||||
const entities = new AllHtmlEntities();
|
||||
|
||||
const Modal = styled(PFModal)`
|
||||
--pf-c-modal-box__footer--MarginTop: 0;
|
||||
align-self: flex-start;
|
||||
margin-top: 200px;
|
||||
.pf-c-modal-box__body {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.pf-c-tab-content {
|
||||
padding: 24px 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const HostNameDetailValue = styled.div`
|
||||
align-items: center;
|
||||
display: inline-grid;
|
||||
@ -31,31 +19,6 @@ const HostNameDetailValue = styled.div`
|
||||
grid-template-columns: auto auto;
|
||||
`;
|
||||
|
||||
const Tabs = styled(PFTabs)`
|
||||
--pf-c-tabs__button--PaddingLeft: 20px;
|
||||
--pf-c-tabs__button--PaddingRight: 20px;
|
||||
|
||||
.pf-c-tabs__list {
|
||||
li:first-of-type .pf-c-tabs__button {
|
||||
&::after {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.pf-c-tabs__item)::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
content: '';
|
||||
border-bottom: solid var(--pf-c-tabs__item--BorderColor);
|
||||
border-width: var(--pf-c-tabs__item--BorderWidth) 0
|
||||
var(--pf-c-tabs__item--BorderWidth) 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const processEventStatus = event => {
|
||||
let status = null;
|
||||
if (event.event === 'runner_on_unreachable') {
|
||||
@ -133,11 +96,11 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false, i18n }) {
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isFooterLeftAligned
|
||||
isLarge
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
title={i18n._(t`Host Details`)}
|
||||
aria-label={i18n._(t`Host details modal`)}
|
||||
width="75%"
|
||||
>
|
||||
<Tabs
|
||||
aria-label={i18n._(t`Tabs`)}
|
||||
@ -147,9 +110,12 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false, i18n }) {
|
||||
<Tab
|
||||
aria-label={i18n._(t`Details tab`)}
|
||||
eventKey={0}
|
||||
title={i18n._(t`Details`)}
|
||||
title={<TabTitleText>{i18n._(t`Details`)}</TabTitleText>}
|
||||
>
|
||||
<DetailList style={{ alignItems: 'center' }} gutter="sm">
|
||||
<DetailList
|
||||
style={{ alignItems: 'center', marginTop: '20px' }}
|
||||
gutter="sm"
|
||||
>
|
||||
<Detail
|
||||
label={i18n._(t`Host Name`)}
|
||||
value={
|
||||
@ -175,7 +141,7 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false, i18n }) {
|
||||
</Tab>
|
||||
<Tab
|
||||
eventKey={1}
|
||||
title={i18n._(t`JSON`)}
|
||||
title={<TabTitleText>{i18n._(t`JSON`)}</TabTitleText>}
|
||||
aria-label={i18n._(t`JSON tab`)}
|
||||
>
|
||||
{activeTabKey === 1 && jsonObj ? (
|
||||
@ -193,7 +159,7 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false, i18n }) {
|
||||
</Tab>
|
||||
<Tab
|
||||
eventKey={2}
|
||||
title={i18n._(t`Standard Out`)}
|
||||
title={<TabTitleText>{i18n._(t`Standard Out`)}</TabTitleText>}
|
||||
aria-label={i18n._(t`Standard out tab`)}
|
||||
>
|
||||
{activeTabKey === 2 && stdOut ? (
|
||||
@ -211,7 +177,7 @@ function HostEventModal({ onClose, hostEvent = {}, isOpen = false, i18n }) {
|
||||
</Tab>
|
||||
<Tab
|
||||
eventKey={3}
|
||||
title={i18n._(t`Standard Error`)}
|
||||
title={<TabTitleText>{i18n._(t`Standard Error`)}</TabTitleText>}
|
||||
aria-label={i18n._(t`Standard error tab`)}
|
||||
>
|
||||
{activeTabKey === 3 && stdErr ? (
|
||||
|
||||
@ -88,16 +88,7 @@ describe('HostEventModal', () => {
|
||||
);
|
||||
|
||||
/* eslint-disable react/button-has-type */
|
||||
expect(
|
||||
wrapper
|
||||
.find('Tabs')
|
||||
.containsAllMatchingElements([
|
||||
<button aria-label="Details tab">Details</button>,
|
||||
<button aria-label="JSON tab">JSON</button>,
|
||||
<button aria-label="Standard out tab">Standard Out</button>,
|
||||
<button aria-label="Standard error tab">Standard Error</button>,
|
||||
])
|
||||
).toEqual(true);
|
||||
expect(wrapper.find('Tabs TabButton').length).toEqual(4);
|
||||
});
|
||||
|
||||
test('should show details tab content on mount', () => {
|
||||
|
||||
@ -475,6 +475,7 @@ class JobOutput extends Component {
|
||||
variant="danger"
|
||||
onClose={() => this.setState({ deletionError: null })}
|
||||
title={i18n._(t`Job Delete Error`)}
|
||||
label={i18n._(t`Job Delete Error`)}
|
||||
>
|
||||
<ErrorDetail error={deletionError} />
|
||||
</AlertModal>
|
||||
|
||||
@ -338,7 +338,7 @@ describe('<JobOutput />', () => {
|
||||
wrapper.find('Modal button[aria-label="Delete"]').simulate('click');
|
||||
await waitForElement(wrapper, 'Modal ErrorDetail');
|
||||
const errorModalCloseBtn = wrapper.find(
|
||||
'ModalBox div[aria-label="Job Delete Error"] button[aria-label="Close"]'
|
||||
'ModalBox[aria-label="Job Delete Error"] ModalBoxCloseButton'
|
||||
);
|
||||
errorModalCloseBtn.simulate('click');
|
||||
await waitForElement(wrapper, 'Modal ErrorDetail', el => el.length === 0);
|
||||
|
||||
@ -15,7 +15,9 @@ class JobsSettings extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`Jobs Settings`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`Jobs Settings`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -15,7 +15,9 @@ class License extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`License`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`License`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -15,7 +15,9 @@ class ManagementJobs extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`Management Jobs`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`Management Jobs`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -15,7 +15,9 @@ class NotificationTemplates extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`Notification Templates`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`Notification Templates`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -2,9 +2,8 @@ import React, { Component } from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Switch, Route, withRouter, Redirect, Link } from 'react-router-dom';
|
||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import NotificationList from '../../components/NotificationList/NotificationList';
|
||||
@ -116,6 +115,16 @@ class Organization extends Component {
|
||||
(me.is_system_auditor || isAuditorOfThisOrg || isAdminOfThisOrg);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Organizations`)}
|
||||
</>
|
||||
),
|
||||
link: `/organizations`,
|
||||
id: 99,
|
||||
},
|
||||
{ name: i18n._(t`Details`), link: `${match.url}/details`, id: 0 },
|
||||
{ name: i18n._(t`Access`), link: `${match.url}/access`, id: 1 },
|
||||
{ name: i18n._(t`Teams`), link: `${match.url}/teams`, id: 2 },
|
||||
@ -129,21 +138,10 @@ class Organization extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
let cardHeader = (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/organizations" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
let showCardHeader = true;
|
||||
|
||||
if (!isInitialized) {
|
||||
cardHeader = null;
|
||||
}
|
||||
|
||||
if (location.pathname.endsWith('edit')) {
|
||||
cardHeader = null;
|
||||
if (!isInitialized || location.pathname.endsWith('edit')) {
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
if (!hasContentLoading && contentError) {
|
||||
@ -168,7 +166,7 @@ class Organization extends Component {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{cardHeader}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect
|
||||
from="/organizations/:id"
|
||||
|
||||
@ -53,7 +53,7 @@ describe('<Organization />', () => {
|
||||
const tabs = await waitForElement(
|
||||
wrapper,
|
||||
'.pf-c-tabs__item',
|
||||
el => el.length === 4
|
||||
el => el.length === 5
|
||||
);
|
||||
expect(tabs.last().text()).toEqual('Notifications');
|
||||
done();
|
||||
@ -74,7 +74,7 @@ describe('<Organization />', () => {
|
||||
const tabs = await waitForElement(
|
||||
wrapper,
|
||||
'.pf-c-tabs__item',
|
||||
el => el.length === 3
|
||||
el => el.length === 4
|
||||
);
|
||||
tabs.forEach(tab => expect(tab.text()).not.toEqual('Notifications'));
|
||||
done();
|
||||
|
||||
@ -15,7 +15,9 @@ class Portal extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`My View`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`My View`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -2,9 +2,8 @@ import React, { Component } from 'react';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Switch, Route, withRouter, Redirect, Link } from 'react-router-dom';
|
||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import NotificationList from '../../components/NotificationList';
|
||||
@ -121,6 +120,16 @@ class Project extends Component {
|
||||
const canToggleNotifications = isNotifAdmin;
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Projects`)}
|
||||
</>
|
||||
),
|
||||
link: `/projects`,
|
||||
id: 99,
|
||||
},
|
||||
{ name: i18n._(t`Details`), link: `${match.url}/details` },
|
||||
{ name: i18n._(t`Access`), link: `${match.url}/access` },
|
||||
];
|
||||
@ -148,24 +157,14 @@ class Project extends Component {
|
||||
tab.id = n;
|
||||
});
|
||||
|
||||
let cardHeader = (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/projects" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
|
||||
if (!isInitialized) {
|
||||
cardHeader = null;
|
||||
}
|
||||
let showCardHeader = true;
|
||||
|
||||
if (
|
||||
!isInitialized ||
|
||||
location.pathname.endsWith('edit') ||
|
||||
location.pathname.includes('schedules/')
|
||||
) {
|
||||
cardHeader = null;
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
if (!hasContentLoading && contentError) {
|
||||
@ -188,7 +187,7 @@ class Project extends Component {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{cardHeader}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect from="/projects/:id" to="/projects/:id/details" exact />
|
||||
{project && (
|
||||
|
||||
@ -44,9 +44,9 @@ describe('<Project />', () => {
|
||||
const tabs = await waitForElement(
|
||||
wrapper,
|
||||
'.pf-c-tabs__item',
|
||||
el => el.length === 5
|
||||
el => el.length === 6
|
||||
);
|
||||
expect(tabs.at(2).text()).toEqual('Notifications');
|
||||
expect(tabs.at(3).text()).toEqual('Notifications');
|
||||
done();
|
||||
});
|
||||
|
||||
@ -65,7 +65,7 @@ describe('<Project />', () => {
|
||||
const tabs = await waitForElement(
|
||||
wrapper,
|
||||
'.pf-c-tabs__item',
|
||||
el => el.length === 4
|
||||
el => el.length === 5
|
||||
);
|
||||
tabs.forEach(tab => expect(tab.text()).not.toEqual('Notifications'));
|
||||
done();
|
||||
@ -86,9 +86,9 @@ describe('<Project />', () => {
|
||||
const tabs = await waitForElement(
|
||||
wrapper,
|
||||
'.pf-c-tabs__item',
|
||||
el => el.length === 4
|
||||
el => el.length === 5
|
||||
);
|
||||
expect(tabs.at(3).text()).toEqual('Schedules');
|
||||
expect(tabs.at(4).text()).toEqual('Schedules');
|
||||
done();
|
||||
});
|
||||
|
||||
@ -108,7 +108,7 @@ describe('<Project />', () => {
|
||||
const tabs = await waitForElement(
|
||||
wrapper,
|
||||
'.pf-c-tabs__item',
|
||||
el => el.length === 3
|
||||
el => el.length === 4
|
||||
);
|
||||
tabs.forEach(tab => expect(tab.text()).not.toEqual('Schedules'));
|
||||
done();
|
||||
|
||||
@ -172,7 +172,9 @@ function ProjectFormFields({
|
||||
fieldId="project-scm-type"
|
||||
helperTextInvalid={scmTypeMeta.error}
|
||||
isRequired
|
||||
isValid={!scmTypeMeta.touched || !scmTypeMeta.error}
|
||||
validated={
|
||||
!scmTypeMeta.touched || !scmTypeMeta.error ? 'default' : 'error'
|
||||
}
|
||||
label={i18n._(t`Source Control Credential Type`)}
|
||||
>
|
||||
<AnsibleSelect
|
||||
@ -204,7 +206,9 @@ function ProjectFormFields({
|
||||
</FormGroup>
|
||||
{formik.values.scm_type !== '' && (
|
||||
<SubFormLayout>
|
||||
<Title size="md">{i18n._(t`Type Details`)}</Title>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{i18n._(t`Type Details`)}
|
||||
</Title>
|
||||
<FormColumnLayout>
|
||||
{
|
||||
{
|
||||
|
||||
@ -81,7 +81,7 @@ const ManualSubForm = ({
|
||||
fieldId="project-local-path"
|
||||
helperTextInvalid={pathMeta.error}
|
||||
isRequired
|
||||
isValid={!pathMeta.touched || !pathMeta.error}
|
||||
validated={!pathMeta.touched || !pathMeta.error ? 'default' : 'error'}
|
||||
label={i18n._(t`Playbook Directory`)}
|
||||
>
|
||||
<FieldTooltip
|
||||
|
||||
@ -104,7 +104,9 @@ export const ScmTypeOptions = withI18n()(
|
||||
|
||||
{scmUpdateOnLaunch && (
|
||||
<>
|
||||
<Title size="md">{i18n._(t`Option Details`)}</Title>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{i18n._(t`Option Details`)}
|
||||
</Title>
|
||||
<FormField
|
||||
id="project-cache-timeout"
|
||||
name="scm_update_cache_timeout"
|
||||
|
||||
@ -15,7 +15,9 @@ class SystemSettings extends Component {
|
||||
return (
|
||||
<Fragment>
|
||||
<PageSection variant={light} className="pf-m-condensed">
|
||||
<Title size="2xl">{i18n._(t`System Settings`)}</Title>
|
||||
<Title size="2xl" headingLevel="h2">
|
||||
{i18n._(t`System Settings`)}
|
||||
</Title>
|
||||
</PageSection>
|
||||
<PageSection />
|
||||
</Fragment>
|
||||
|
||||
@ -9,9 +9,8 @@ import {
|
||||
useLocation,
|
||||
useParams,
|
||||
} from 'react-router-dom';
|
||||
import { Card, CardActions, PageSection } from '@patternfly/react-core';
|
||||
import CardCloseButton from '../../components/CardCloseButton';
|
||||
import { TabbedCardHeader } from '../../components/Card';
|
||||
import { CaretLeftIcon } from '@patternfly/react-icons';
|
||||
import { Card, PageSection } from '@patternfly/react-core';
|
||||
import RoutedTabs from '../../components/RoutedTabs';
|
||||
import ContentError from '../../components/ContentError';
|
||||
import TeamDetail from './TeamDetail';
|
||||
@ -41,22 +40,25 @@ function Team({ i18n, setBreadcrumb }) {
|
||||
}, [id, setBreadcrumb, location]);
|
||||
|
||||
const tabsArray = [
|
||||
{
|
||||
name: (
|
||||
<>
|
||||
<CaretLeftIcon />
|
||||
{i18n._(t`Back to Teams`)}
|
||||
</>
|
||||
),
|
||||
link: `/teams`,
|
||||
id: 99,
|
||||
},
|
||||
{ name: i18n._(t`Details`), link: `/teams/${id}/details`, id: 0 },
|
||||
{ name: i18n._(t`Users`), link: `/teams/${id}/users`, id: 1 },
|
||||
{ name: i18n._(t`Access`), link: `/teams/${id}/access`, id: 2 },
|
||||
];
|
||||
|
||||
let cardHeader = (
|
||||
<TabbedCardHeader>
|
||||
<RoutedTabs tabsArray={tabsArray} />
|
||||
<CardActions>
|
||||
<CardCloseButton linkTo="/teams" />
|
||||
</CardActions>
|
||||
</TabbedCardHeader>
|
||||
);
|
||||
let showCardHeader = true;
|
||||
|
||||
if (location.pathname.endsWith('edit')) {
|
||||
cardHeader = null;
|
||||
showCardHeader = false;
|
||||
}
|
||||
|
||||
if (!hasContentLoading && contentError) {
|
||||
@ -79,7 +81,7 @@ function Team({ i18n, setBreadcrumb }) {
|
||||
return (
|
||||
<PageSection>
|
||||
<Card>
|
||||
{cardHeader}
|
||||
{showCardHeader && <RoutedTabs tabsArray={tabsArray} />}
|
||||
<Switch>
|
||||
<Redirect from="/teams/:id" to="/teams/:id/details" exact />
|
||||
{team && (
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user