Merge pull request #6486 from keithjgrant/5909-jt-launch-prompt

JT Launch Prompting (phase 1)

Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
softwarefactory-project-zuul[bot] 2020-04-01 18:29:27 +00:00 committed by GitHub
commit e5f293ce52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 865 additions and 49 deletions

View File

@ -4910,6 +4910,201 @@
}
}
},
"@jest/transform": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.1.0.tgz",
"integrity": "sha512-4ktrQ2TPREVeM+KxB4zskAT84SnmG1vaz4S+51aTefyqn3zocZUnliLLm5Fsl85I3p/kFPN4CRp1RElIfXGegQ==",
"dev": true,
"requires": {
"@babel/core": "^7.1.0",
"@jest/types": "^25.1.0",
"babel-plugin-istanbul": "^6.0.0",
"chalk": "^3.0.0",
"convert-source-map": "^1.4.0",
"fast-json-stable-stringify": "^2.0.0",
"graceful-fs": "^4.2.3",
"jest-haste-map": "^25.1.0",
"jest-regex-util": "^25.1.0",
"jest-util": "^25.1.0",
"micromatch": "^4.0.2",
"pirates": "^4.0.1",
"realpath-native": "^1.1.0",
"slash": "^3.0.0",
"source-map": "^0.6.1",
"write-file-atomic": "^3.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"graceful-fs": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"jest-regex-util": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-25.1.0.tgz",
"integrity": "sha512-9lShaDmDpqwg+xAd73zHydKrBbbrIi08Kk9YryBEBybQFg/lBWR/2BDjjiSE7KIppM9C5+c03XiDaZ+m4Pgs1w==",
"dev": true
},
"micromatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
"dev": true,
"requires": {
"braces": "^3.0.1",
"picomatch": "^2.0.5"
}
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
}
}
},
"@jest/types": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/@jest/types/-/types-25.1.0.tgz",
"integrity": "sha512-VpOtt7tCrgvamWZh1reVsGADujKigBUFTi19mlRjqEGsE8qH4r3s+skY33dNdXOwyZIvuftZ5tqdF1IgsMejMA==",
"dev": true,
"requires": {
"@types/istanbul-lib-coverage": "^2.0.0",
"@types/istanbul-reports": "^1.1.1",
"@types/yargs": "^15.0.0",
"chalk": "^3.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"@lingui/babel-plugin-extract-messages": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/@lingui/babel-plugin-extract-messages/-/babel-plugin-extract-messages-2.7.4.tgz",
@ -5260,6 +5455,15 @@
"integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
"dev": true
},
"@types/yargs": {
"version": "15.0.4",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz",
"integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==",
"dev": true,
"requires": {
"@types/yargs-parser": "*"
}
},
"@types/yargs-parser": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
@ -6330,6 +6534,73 @@
}
}
},
"babel-jest": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.1.0.tgz",
"integrity": "sha512-tz0VxUhhOE2y+g8R2oFrO/2VtVjA1lkJeavlhExuRBg3LdNJY9gwQ+Vcvqt9+cqy71MCTJhewvTB7Qtnnr9SWg==",
"dev": true,
"requires": {
"@jest/transform": "^25.1.0",
"@jest/types": "^25.1.0",
"@types/babel__core": "^7.1.0",
"babel-plugin-istanbul": "^6.0.0",
"babel-preset-jest": "^25.1.0",
"chalk": "^3.0.0",
"slash": "^3.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"babel-loader": {
"version": "8.0.6",
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz",
@ -6407,6 +6678,15 @@
"test-exclude": "^6.0.0"
}
},
"babel-plugin-jest-hoist": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.1.0.tgz",
"integrity": "sha512-oIsopO41vW4YFZ9yNYoLQATnnN46lp+MZ6H4VvPKFkcc2/fkl3CfE/NZZSmnEIEsJRmJAgkVEK0R7Zbl50CpTw==",
"dev": true,
"requires": {
"@types/babel__traverse": "^7.0.6"
}
},
"babel-plugin-macros": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.4.2.tgz",
@ -6451,6 +6731,17 @@
}
}
},
"babel-preset-jest": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-25.1.0.tgz",
"integrity": "sha512-eCGn64olaqwUMaugXsTtGAM2I0QTahjEtnRu0ql8Ie+gDWAc1N6wqN0k2NilnyTunM69Pad7gJY7LOtwLimoFQ==",
"dev": true,
"requires": {
"@babel/plugin-syntax-bigint": "^7.0.0",
"@babel/plugin-syntax-object-rest-spread": "^7.0.0",
"babel-plugin-jest-hoist": "^25.1.0"
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@ -14622,6 +14913,99 @@
"integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==",
"dev": true
},
"jest-haste-map": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.1.0.tgz",
"integrity": "sha512-/2oYINIdnQZAqyWSn1GTku571aAfs8NxzSErGek65Iu5o8JYb+113bZysRMcC/pjE5v9w0Yz+ldbj9NxrFyPyw==",
"dev": true,
"requires": {
"@jest/types": "^25.1.0",
"anymatch": "^3.0.3",
"fb-watchman": "^2.0.0",
"fsevents": "^2.1.2",
"graceful-fs": "^4.2.3",
"jest-serializer": "^25.1.0",
"jest-util": "^25.1.0",
"jest-worker": "^25.1.0",
"micromatch": "^4.0.2",
"sane": "^4.0.3",
"walker": "^1.0.7"
},
"dependencies": {
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"requires": {
"fill-range": "^7.0.1"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
},
"fsevents": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
"integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
"dev": true,
"optional": true
},
"graceful-fs": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
"dev": true
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true
},
"micromatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
"integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==",
"dev": true,
"requires": {
"braces": "^3.0.1",
"picomatch": "^2.0.5"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"requires": {
"is-number": "^7.0.0"
}
}
}
},
"jest-jasmine2": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-25.1.0.tgz",
@ -15941,6 +16325,12 @@
}
}
},
"jest-serializer": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.1.0.tgz",
"integrity": "sha512-20Wkq5j7o84kssBwvyuJ7Xhn7hdPeTXndnwIblKDR2/sy1SUm6rWWiG9kSCgJPIfkDScJCIsTtOKdlzfIHOfKA==",
"dev": true
},
"jest-snapshot": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.1.0.tgz",
@ -16239,6 +16629,70 @@
}
}
},
"jest-util": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.1.0.tgz",
"integrity": "sha512-7did6pLQ++87Qsj26Fs/TIwZMUFBXQ+4XXSodRNy3luch2DnRXsSnmpVtxxQ0Yd6WTipGpbhh2IFP1mq6/fQGw==",
"dev": true,
"requires": {
"@jest/types": "^25.1.0",
"chalk": "^3.0.0",
"is-ci": "^2.0.0",
"mkdirp": "^0.5.1"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"jest-validate": {
"version": "23.6.0",
"resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz",

View File

@ -15,6 +15,7 @@ import {
WorkflowJobsAPI,
WorkflowJobTemplatesAPI,
} from '@api';
import LaunchPrompt from '@components/LaunchPrompt';
function canLaunchWithoutPrompt(launchData) {
return (
@ -24,7 +25,8 @@ function canLaunchWithoutPrompt(launchData) {
!launchData.ask_limit_on_launch &&
!launchData.ask_scm_branch_on_launch &&
!launchData.survey_enabled &&
launchData.variables_needed_to_start.length === 0
(!launchData.variables_needed_to_start ||
launchData.variables_needed_to_start.length === 0)
);
}
@ -39,11 +41,13 @@ class LaunchButton extends React.Component {
super(props);
this.state = {
launchError: null,
promptError: false,
showLaunchPrompt: false,
launchConfig: null,
launchError: false,
};
this.handleLaunch = this.handleLaunch.bind(this);
this.launchWithParams = this.launchWithParams.bind(this);
this.handleRelaunch = this.handleRelaunch.bind(this);
this.handleLaunchErrorClose = this.handleLaunchErrorClose.bind(this);
this.handlePromptErrorClose = this.handlePromptErrorClose.bind(this);
@ -54,41 +58,50 @@ class LaunchButton extends React.Component {
}
handlePromptErrorClose() {
this.setState({ promptError: false });
this.setState({ showLaunchPrompt: false });
}
async handleLaunch() {
const { history, resource } = this.props;
const { resource } = this.props;
const readLaunch =
resource.type === 'workflow_job_template'
? WorkflowJobTemplatesAPI.readLaunch(resource.id)
: JobTemplatesAPI.readLaunch(resource.id);
const launchJob =
resource.type === 'workflow_job_template'
? WorkflowJobTemplatesAPI.launch(resource.id)
: JobTemplatesAPI.launch(resource.id);
try {
const { data: launchConfig } = await readLaunch;
if (canLaunchWithoutPrompt(launchConfig)) {
const { data: job } = await launchJob;
history.push(
`/${
resource.type === 'workflow_job_template' ? 'jobs/workflow' : 'jobs'
}/${job.id}/output`
);
this.launchWithParams(null);
} else {
this.setState({ promptError: true });
this.setState({
showLaunchPrompt: true,
launchConfig,
});
}
} catch (err) {
this.setState({ launchError: err });
}
}
async launchWithParams(params) {
try {
const { history, resource } = this.props;
const jobPromise =
resource.type === 'workflow_job_template'
? WorkflowJobTemplatesAPI.launch(resource.id, params)
: JobTemplatesAPI.launch(resource.id, params);
const { data: job } = await jobPromise;
history.push(
`/${
resource.type === 'workflow_job_template' ? 'jobs/workflow' : 'jobs'
}/${job.id}/output`
);
} catch (launchError) {
this.setState({ launchError });
}
}
async handleRelaunch() {
const { history, resource } = this.props;
@ -125,7 +138,12 @@ class LaunchButton extends React.Component {
const { data: job } = await relaunch;
history.push(`/jobs/${job.id}/output`);
} else {
this.setState({ promptError: true });
// TODO: restructure (async?) to send launch command after prompts
// TODO: does relaunch need different prompt treatment than launch?
this.setState({
showLaunchPrompt: true,
launchConfig: relaunchConfig,
});
}
} catch (err) {
this.setState({ launchError: err });
@ -133,8 +151,8 @@ class LaunchButton extends React.Component {
}
render() {
const { launchError, promptError } = this.state;
const { i18n, children } = this.props;
const { launchError, showLaunchPrompt, launchConfig } = this.state;
const { resource, i18n, children } = this.props;
return (
<Fragment>
{children({
@ -152,17 +170,13 @@ class LaunchButton extends React.Component {
<ErrorDetail error={launchError} />
</AlertModal>
)}
{promptError && (
<AlertModal
isOpen={promptError}
variant="info"
title={i18n._(t`Attention!`)}
onClose={this.handlePromptErrorClose}
>
{i18n._(
t`Launching jobs with promptable fields is not supported at this time.`
)}
</AlertModal>
{showLaunchPrompt && (
<LaunchPrompt
config={launchConfig}
resource={resource}
onLaunch={this.launchWithParams}
onCancel={() => this.setState({ showLaunchPrompt: false })}
/>
)}
</Fragment>
);

View File

@ -30,7 +30,9 @@ describe('LaunchButton', () => {
id: 1,
type: 'job_template',
};
afterEach(() => jest.clearAllMocks());
test('renders the expected content', () => {
const wrapper = mountWithContexts(
<LaunchButton resource={resource}>{children}</LaunchButton>
@ -60,9 +62,10 @@ describe('LaunchButton', () => {
button.prop('onClick')();
expect(JobTemplatesAPI.readLaunch).toHaveBeenCalledWith(1);
await sleep(0);
expect(JobTemplatesAPI.launch).toHaveBeenCalledWith(1);
expect(JobTemplatesAPI.launch).toHaveBeenCalledWith(1, null);
expect(history.location.pathname).toEqual('/jobs/9000/output');
});
test('should launch the correct job type', async () => {
WorkflowJobTemplatesAPI.readLaunch.mockResolvedValue({
data: {
@ -72,7 +75,7 @@ describe('LaunchButton', () => {
const history = createMemoryHistory({
initialEntries: ['/jobs/9000'],
});
JobTemplatesAPI.launch.mockResolvedValue({
WorkflowJobTemplatesAPI.launch.mockResolvedValue({
data: {
id: 9000,
},
@ -96,9 +99,10 @@ describe('LaunchButton', () => {
button.prop('onClick')();
expect(WorkflowJobTemplatesAPI.readLaunch).toHaveBeenCalledWith(1);
await sleep(0);
expect(WorkflowJobTemplatesAPI.launch).toHaveBeenCalledWith(1);
expect(history.location.pathname).toEqual('/jobs/9000');
expect(WorkflowJobTemplatesAPI.launch).toHaveBeenCalledWith(1, null);
expect(history.location.pathname).toEqual('/jobs/workflow/9000/output');
});
test('displays error modal after unsuccessful launch', async () => {
const wrapper = mountWithContexts(
<LaunchButton resource={resource}>{children}</LaunchButton>

View File

@ -0,0 +1,7 @@
import React from 'react';
function CredentialsStep() {
return <div />;
}
export default CredentialsStep;

View File

@ -0,0 +1,86 @@
import React, { useCallback, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { useField } from 'formik';
import { InventoriesAPI } from '@api';
import { getQSConfig, parseQueryString } from '@util/qs';
import useRequest from '@util/useRequest';
import OptionsList from '@components/OptionsList';
import ContentLoading from '@components/ContentLoading';
const QS_CONFIG = getQSConfig('inventory', {
page: 1,
page_size: 5,
order_by: 'name',
});
function InventoryStep({ i18n }) {
const history = useHistory();
const [field, , helpers] = useField('inventory');
const {
isLoading,
// error,
result: { inventories, count },
request: fetchInventories,
} = useRequest(
useCallback(async () => {
const params = parseQueryString(QS_CONFIG, history.location.search);
const { data } = await InventoriesAPI.read(params);
return {
inventories: data.results,
count: data.count,
};
}, [history.location]),
{
count: 0,
inventories: [],
}
);
useEffect(() => {
fetchInventories();
}, [fetchInventories]);
if (isLoading) {
return <ContentLoading />;
}
return (
<OptionsList
value={field.value ? [field.value] : []}
options={inventories}
optionCount={count}
searchColumns={[
{
name: i18n._(t`Name`),
key: 'name',
isDefault: true,
},
{
name: i18n._(t`Created By (Username)`),
key: 'created_by__username',
},
{
name: i18n._(t`Modified By (Username)`),
key: 'modified_by__username',
},
]}
sortColumns={[
{
name: i18n._(t`Name`),
key: 'name',
},
]}
header={i18n._(t`Inventory`)}
name="inventory"
qsConfig={QS_CONFIG}
readOnly
selectItem={helpers.setValue}
deselectItem={() => field.onChange(null)}
/>
);
}
export default withI18n()(InventoryStep);

View File

@ -0,0 +1,40 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { Formik } from 'formik';
import { mountWithContexts } from '@testUtils/enzymeHelpers';
import InventoryStep from './InventoryStep';
import { InventoriesAPI } from '@api';
jest.mock('@api/models/Inventories');
const inventories = [
{ id: 1, name: 'inv one', url: '/inventories/1' },
{ id: 2, name: 'inv two', url: '/inventories/2' },
{ id: 3, name: 'inv three', url: '/inventories/3' },
];
describe('InventoryStep', () => {
beforeEach(() => {
InventoriesAPI.read.mockResolvedValue({
data: {
results: inventories,
count: 3,
},
});
});
test('should load inventories', async () => {
let wrapper;
await act(async () => {
wrapper = mountWithContexts(
<Formik>
<InventoryStep />
</Formik>
);
});
wrapper.update();
expect(InventoriesAPI.read).toHaveBeenCalled();
expect(wrapper.find('OptionsList').prop('options')).toEqual(inventories);
});
});

View File

@ -0,0 +1,88 @@
import React from 'react';
import { Wizard } from '@patternfly/react-core';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Formik } from 'formik';
import InventoryStep from './InventoryStep';
import CredentialsStep from './CredentialsStep';
import OtherPromptsStep from './OtherPromptsStep';
import SurveyStep from './SurveyStep';
import PreviewStep from './PreviewStep';
function LaunchPrompt({ config, resource, onLaunch, onCancel, i18n }) {
const steps = [];
const initialValues = {};
if (config.ask_inventory_on_launch) {
initialValues.inventory = resource?.summary_fields?.inventory || null;
steps.push({
name: i18n._(t`Inventory`),
component: <InventoryStep />,
});
}
// TODO: match old UI Logic:
// if (vm.promptDataClone.launchConf.ask_credential_on_launch ||
// (_.has(vm, 'promptDataClone.prompts.credentials.passwords.vault') &&
// vm.promptDataClone.prompts.credentials.passwords.vault.length > 0) ||
// _.has(vm, 'promptDataClone.prompts.credentials.passwords.ssh_key_unlock') ||
// _.has(vm, 'promptDataClone.prompts.credentials.passwords.become_password') ||
// _.has(vm, 'promptDataClone.prompts.credentials.passwords.ssh_password')
// ) {
if (config.ask_credential_on_launch) {
initialValues.credentials = resource?.summary_fields?.credentials || [];
steps.push({
name: i18n._(t`Credential`),
component: <CredentialsStep />,
});
}
if (
config.ask_scm_branch_on_launch ||
(config.ask_variables_on_launch && !config.ignore_ask_variables) ||
config.ask_tags_on_launch ||
config.ask_diff_mode_on_launch ||
config.ask_skip_tags_on_launch ||
config.ask_job_type_on_launch ||
config.ask_limit_on_launch ||
config.ask_verbosity_on_launch
) {
steps.push({
name: i18n._(t`Other Prompts`),
component: <OtherPromptsStep config={config} />,
});
}
if (config.survey_enabled) {
steps.push({
name: i18n._(t`Survey`),
component: <SurveyStep />,
});
}
steps.push({
name: i18n._(t`Preview`),
component: <PreviewStep />,
nextButtonText: i18n._(t`Launch`),
});
const submit = values => {
const postValues = {};
if (values.inventory) {
postValues.inventory_id = values.inventory.id;
}
onLaunch(postValues);
};
return (
<Formik initialValues={initialValues} onSubmit={submit}>
{({ handleSubmit }) => (
<Wizard
isOpen
onClose={onCancel}
onSave={handleSubmit}
title={i18n._(t`Prompts`)}
steps={steps}
/>
)}
</Formik>
);
}
export { LaunchPrompt as _LaunchPrompt };
export default withI18n()(LaunchPrompt);

View File

@ -0,0 +1,100 @@
import React from 'react';
import { act, isElementOfType } from 'react-dom/test-utils';
import { mountWithContexts } from '@testUtils/enzymeHelpers';
import LaunchPrompt from './LaunchPrompt';
import InventoryStep from './InventoryStep';
import PreviewStep from './PreviewStep';
import { InventoriesAPI } from '@api';
jest.mock('@api/models/Inventories');
let config;
const resource = {
id: 1,
type: 'job_template',
};
const noop = () => {};
describe('LaunchPrompt', () => {
beforeEach(() => {
InventoriesAPI.read.mockResolvedValue({
data: {
results: [{ id: 1, name: 'foo', url: '/inventories/1' }],
count: 1,
},
});
config = {
can_start_without_user_input: false,
passwords_needed_to_start: [],
ask_scm_branch_on_launch: false,
ask_variables_on_launch: false,
ask_tags_on_launch: false,
ask_diff_mode_on_launch: false,
ask_skip_tags_on_launch: false,
ask_job_type_on_launch: false,
ask_limit_on_launch: false,
ask_verbosity_on_launch: false,
ask_inventory_on_launch: false,
ask_credential_on_launch: false,
survey_enabled: false,
variables_needed_to_start: [],
credential_needed_to_start: false,
inventory_needed_to_start: false,
job_template_data: { name: 'JT with prompts', id: 25, description: '' },
};
});
afterEach(() => jest.clearAllMocks());
test('should render Wizard with all steps', async () => {
let wrapper;
await act(async () => {
wrapper = mountWithContexts(
<LaunchPrompt
config={{
...config,
ask_inventory_on_launch: true,
ask_credential_on_launch: true,
ask_scm_branch_on_launch: true,
survey_enabled: true,
}}
resource={resource}
onLaunch={noop}
onCancel={noop}
/>
);
});
const steps = wrapper.find('Wizard').prop('steps');
expect(steps).toHaveLength(5);
expect(steps[0].name).toEqual('Inventory');
expect(steps[1].name).toEqual('Credential');
expect(steps[2].name).toEqual('Other Prompts');
expect(steps[3].name).toEqual('Survey');
expect(steps[4].name).toEqual('Preview');
});
test('should add inventory step', async () => {
let wrapper;
await act(async () => {
wrapper = mountWithContexts(
<LaunchPrompt
config={{
...config,
ask_inventory_on_launch: true,
}}
resource={resource}
onLaunch={noop}
onCancel={noop}
/>
);
});
const steps = wrapper.find('Wizard').prop('steps');
expect(steps).toHaveLength(2);
expect(steps[0].name).toEqual('Inventory');
expect(isElementOfType(steps[0].component, InventoryStep)).toEqual(true);
expect(isElementOfType(steps[1].component, PreviewStep)).toEqual(true);
});
});

View File

@ -0,0 +1,7 @@
import React from 'react';
function InventoryStep() {
return <div />;
}
export default InventoryStep;

View File

@ -0,0 +1,7 @@
import React from 'react';
function PreviewStep() {
return <div>Preview of selected values will appear here</div>;
}
export default PreviewStep;

View File

@ -0,0 +1,7 @@
import React from 'react';
function InventoryStep() {
return <div />;
}
export default InventoryStep;

View File

@ -0,0 +1 @@
export { default } from './LaunchPrompt';

View File

@ -9,7 +9,7 @@ import { getQSConfig, parseQueryString, mergeParams } from '@util/qs';
import { FieldTooltip } from '@components/FormField';
import { FormGroup } from '@patternfly/react-core';
import Lookup from '@components/Lookup';
import OptionsList from './shared/OptionsList';
import OptionsList from '@components/OptionsList';
import LookupErrorMessage from './shared/LookupErrorMessage';
const QS_CONFIG = getQSConfig('credentials', {

View File

@ -7,8 +7,8 @@ import { FormGroup } from '@patternfly/react-core';
import { InstanceGroupsAPI } from '@api';
import { getQSConfig, parseQueryString } from '@util/qs';
import { FieldTooltip } from '@components/FormField';
import OptionsList from '@components/OptionsList';
import Lookup from './Lookup';
import OptionsList from './shared/OptionsList';
import LookupErrorMessage from './shared/LookupErrorMessage';
const QS_CONFIG = getQSConfig('instance_groups', {

View File

@ -6,8 +6,8 @@ import { t } from '@lingui/macro';
import { InventoriesAPI } from '@api';
import { Inventory } from '@types';
import Lookup from '@components/Lookup';
import OptionsList from '@components/OptionsList';
import { getQSConfig, parseQueryString } from '@util/qs';
import OptionsList from './shared/OptionsList';
import LookupErrorMessage from './shared/LookupErrorMessage';
const QS_CONFIG = getQSConfig('inventory', {

View File

@ -7,9 +7,9 @@ import { ToolbarItem, Alert } from '@patternfly/react-core';
import { CredentialsAPI, CredentialTypesAPI } from '@api';
import AnsibleSelect from '@components/AnsibleSelect';
import CredentialChip from '@components/CredentialChip';
import OptionsList from '@components/OptionsList';
import { getQSConfig, parseQueryString } from '@util/qs';
import Lookup from './Lookup';
import OptionsList from './shared/OptionsList';
const QS_CONFIG = getQSConfig('credentials', {
page: 1,

View File

@ -7,8 +7,8 @@ import { OrganizationsAPI } from '@api';
import { Organization } from '@types';
import { FormGroup } from '@patternfly/react-core';
import { getQSConfig, parseQueryString } from '@util/qs';
import OptionsList from '@components/OptionsList';
import Lookup from './Lookup';
import OptionsList from './shared/OptionsList';
import LookupErrorMessage from './shared/LookupErrorMessage';
const QS_CONFIG = getQSConfig('organizations', {

View File

@ -7,9 +7,9 @@ import { FormGroup } from '@patternfly/react-core';
import { ProjectsAPI } from '@api';
import { Project } from '@types';
import { FieldTooltip } from '@components/FormField';
import OptionsList from '@components/OptionsList';
import { getQSConfig, parseQueryString } from '@util/qs';
import Lookup from './Lookup';
import OptionsList from './shared/OptionsList';
import LookupErrorMessage from './shared/LookupErrorMessage';
const QS_CONFIG = getQSConfig('project', {

View File

@ -11,10 +11,10 @@ import {
import styled from 'styled-components';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import SelectedList from '../../SelectedList';
import PaginatedDataList from '../../PaginatedDataList';
import CheckboxListItem from '../../CheckboxListItem';
import DataListToolbar from '../../DataListToolbar';
import SelectedList from '../SelectedList';
import PaginatedDataList from '../PaginatedDataList';
import CheckboxListItem from '../CheckboxListItem';
import DataListToolbar from '../DataListToolbar';
import { QSConfig, SearchColumns, SortColumns } from '@types';
const ModalList = styled.div`

View File

@ -0,0 +1 @@
export { default } from './OptionsList';

View File

@ -3,7 +3,7 @@ import { useHistory } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Button, Modal } from '@patternfly/react-core';
import OptionsList from '@components/Lookup/shared/OptionsList';
import OptionsList from '@components/OptionsList';
import useRequest from '@util/useRequest';
import { getQSConfig, parseQueryString } from '@util/qs';
import useSelected from '@util/useSelected';