feat(ux): enhance media-type switching experience in RequestBodyEditor (#6837)
* feat(ux): enhance media-type switching experience in RequestBodyEditor 1. When canceling the try-out mode the request body will be reset to its initial state. 2. When the user switches the media-type in the try-out mode, the experience is as follows: - If the user did edit the request body the body wont be touched and only media type is updated. This is to ensure that user content is NEVER accidentally overwritten with a default value. - If the user did not edit the request body it is safe to be replaced by the default value of the target media-type. Multiple example needed some care in order to allow the retain example value to function properly * fix(test): workaround cypress issue that can't be reproduced manually * test: added new feature to ensure enhanced user editing flow Signed-off-by: mathis-m <mathis.michel@outlook.de>
This commit is contained in:
@@ -36,16 +36,22 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
examples: ImPropTypes.map,
|
||||
onSelect: PropTypes.func,
|
||||
updateValue: PropTypes.func, // mechanism to update upstream value
|
||||
userHasEditedBody: PropTypes.bool,
|
||||
getComponent: PropTypes.func.isRequired,
|
||||
currentUserInputValue: PropTypes.any,
|
||||
currentKey: PropTypes.string,
|
||||
currentNamespace: PropTypes.string,
|
||||
setRetainRequestBodyValueFlag: PropTypes.func.isRequired,
|
||||
// (also proxies props for Examples)
|
||||
}
|
||||
|
||||
static defaultProps = {
|
||||
userHasEditedBody: false,
|
||||
examples: Map({}),
|
||||
currentNamespace: "__DEFAULT__NAMESPACE__",
|
||||
setRetainRequestBodyValueFlag: () => {
|
||||
// NOOP
|
||||
},
|
||||
onSelect: (...args) =>
|
||||
console.log( // eslint-disable-line no-console
|
||||
"ExamplesSelectValueRetainer: no `onSelect` function was provided",
|
||||
@@ -72,11 +78,16 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
lastDownstreamValue: valueFromExample,
|
||||
isModifiedValueSelected:
|
||||
// valueFromExample !== undefined &&
|
||||
this.props.userHasEditedBody ||
|
||||
this.props.currentUserInputValue !== valueFromExample,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.setRetainRequestBodyValueFlag(false)
|
||||
}
|
||||
|
||||
_getStateForCurrentNamespace = () => {
|
||||
const { currentNamespace } = this.props
|
||||
|
||||
@@ -122,7 +133,12 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
}
|
||||
|
||||
_onExamplesSelect = (key, { isSyntheticChange } = {}, ...otherArgs) => {
|
||||
const { onSelect, updateValue, currentUserInputValue } = this.props
|
||||
const {
|
||||
onSelect,
|
||||
updateValue,
|
||||
currentUserInputValue,
|
||||
userHasEditedBody,
|
||||
} = this.props
|
||||
const { lastUserEditedValue } = this._getStateForCurrentNamespace()
|
||||
|
||||
const valueFromExample = this._getValueForExample(key)
|
||||
@@ -141,9 +157,8 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
this._setStateForCurrentNamespace({
|
||||
lastDownstreamValue: valueFromExample,
|
||||
isModifiedValueSelected:
|
||||
isSyntheticChange &&
|
||||
!!currentUserInputValue &&
|
||||
currentUserInputValue !== valueFromExample,
|
||||
(isSyntheticChange && userHasEditedBody) ||
|
||||
(!!currentUserInputValue && currentUserInputValue !== valueFromExample),
|
||||
})
|
||||
|
||||
// we never want to send up value updates from synthetic changes
|
||||
@@ -157,7 +172,12 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// update `lastUserEditedValue` as new currentUserInput values come in
|
||||
|
||||
const { currentUserInputValue: newValue, examples, onSelect } = nextProps
|
||||
const {
|
||||
currentUserInputValue: newValue,
|
||||
examples,
|
||||
onSelect,
|
||||
userHasEditedBody,
|
||||
} = nextProps
|
||||
|
||||
const {
|
||||
lastUserEditedValue,
|
||||
@@ -170,7 +190,7 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
)
|
||||
|
||||
const exampleMatchingNewValue = examples.find(
|
||||
example =>
|
||||
(example) =>
|
||||
example.get("value") === newValue ||
|
||||
// sometimes data is stored as a string (e.g. in Request Bodies), so
|
||||
// let's check against a stringified version of our example too
|
||||
@@ -186,15 +206,23 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
newValue !== lastUserEditedValue && // value isn't already tracked
|
||||
newValue !== lastDownstreamValue // value isn't what we've seen on the other side
|
||||
) {
|
||||
this.props.setRetainRequestBodyValueFlag(true)
|
||||
this._setStateForNamespace(nextProps.currentNamespace, {
|
||||
lastUserEditedValue: nextProps.currentUserInputValue,
|
||||
isModifiedValueSelected: newValue !== valueFromCurrentExample,
|
||||
isModifiedValueSelected:
|
||||
userHasEditedBody || newValue !== valueFromCurrentExample,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currentUserInputValue, examples, currentKey, getComponent } = this.props
|
||||
const {
|
||||
currentUserInputValue,
|
||||
examples,
|
||||
currentKey,
|
||||
getComponent,
|
||||
userHasEditedBody,
|
||||
} = this.props
|
||||
const {
|
||||
lastDownstreamValue,
|
||||
lastUserEditedValue,
|
||||
@@ -212,9 +240,10 @@ export default class ExamplesSelectValueRetainer extends React.PureComponent {
|
||||
!!lastUserEditedValue && lastUserEditedValue !== lastDownstreamValue
|
||||
}
|
||||
isValueModified={
|
||||
currentUserInputValue !== undefined &&
|
||||
isModifiedValueSelected &&
|
||||
currentUserInputValue !== this._getCurrentExampleValue()
|
||||
(currentUserInputValue !== undefined &&
|
||||
isModifiedValueSelected &&
|
||||
currentUserInputValue !== this._getCurrentExampleValue()) ||
|
||||
userHasEditedBody
|
||||
}
|
||||
/>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user