Skip to content

Commit e330c8c

Browse files
authored
Merge pull request #6 from cqframework/edit-request
Added an Edit Request option in the developer panel to enable user to…
2 parents f830439 + 2b5ed33 commit e330c8c

2 files changed

Lines changed: 107 additions & 6 deletions

File tree

src/components/ContextView/context-view.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@
3939
border-bottom: 2px solid #eee;
4040
}
4141

42+
.edit-textarea {
43+
width: 100%;
44+
min-height: 300px;
45+
background: #0D0630;
46+
color: #fff;
47+
font-size: 13px;
48+
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
49+
line-height: 1.5;
50+
padding: 16px;
51+
border: none;
52+
border-radius: 4px;
53+
resize: vertical;
54+
box-sizing: border-box;
55+
}
56+
4257
@media (max-width: 975px) {
4358
.container {
4459
width: 100%;

src/components/ContextView/context-view.jsx

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,21 @@ import PropTypes from 'prop-types';
55
import { connect } from 'react-redux';
66
import cx from 'classnames';
77
import forIn from 'lodash/forIn';
8+
import axios from 'axios';
89

910
import FormControl from '@mui/material/FormControl';
1011
import FormLabel from '@mui/material/FormLabel';
12+
import MuiButton from '@mui/material/Button';
1113
import Select from 'react-select';
1214
import ExchangePanel from '../ExchangePanel/exchange-panel';
1315
import MessagePanel from '../MessagePanel/message-panel';
1416

1517
import styles from './context-view.css';
1618

17-
import { selectService } from '../../actions/service-exchange-actions';
19+
import { selectService, storeExchange } from '../../actions/service-exchange-actions';
1820
import { setContextVisibility } from '../../actions/ui-actions';
1921
import { getServicesByHook } from '../../reducers/helpers/services-filter';
22+
import generateJWT from '../../retrieve-data-helpers/jwt-generator';
2023

2124
const propTypes = {
2225
/**
@@ -48,6 +51,10 @@ const propTypes = {
4851
* Flag to determine if the context view will be visible or not (via the slide out button)
4952
*/
5053
isContextVisible: PropTypes.bool.isRequired,
54+
/**
55+
* Function to store a service exchange (request/response) in the Redux store
56+
*/
57+
storeExchange: PropTypes.func.isRequired,
5158
};
5259

5360
/**
@@ -58,10 +65,18 @@ const propTypes = {
5865
export class ContextView extends Component {
5966
constructor(props) {
6067
super(props);
68+
this.state = {
69+
isEditingRequest: false,
70+
draftRequest: '',
71+
};
6172
this.onSelectChange = this.onSelectChange.bind(this);
6273
this.createDropdownServices = this.createDropdownServices.bind(this);
6374
this.onContextToggle = this.onContextToggle.bind(this);
6475
this.formatOptionLabel = this.formatOptionLabel.bind(this);
76+
this.onEditRequest = this.onEditRequest.bind(this);
77+
this.onCancelEdit = this.onCancelEdit.bind(this);
78+
this.onDraftChange = this.onDraftChange.bind(this);
79+
this.onResend = this.onResend.bind(this);
6580
}
6681

6782
/**
@@ -80,6 +95,53 @@ export class ContextView extends Component {
8095
this.props.toggleContext();
8196
}
8297

98+
onEditRequest() {
99+
const serviceInContext = this.props.selectedService || this.props.initialService;
100+
const serviceExchange = serviceInContext ? this.props.exchanges[serviceInContext] : null;
101+
const request = serviceExchange ? serviceExchange.request : '';
102+
const draft = typeof request === 'string' ? request : JSON.stringify(request, null, 2);
103+
this.setState({ isEditingRequest: true, draftRequest: draft });
104+
}
105+
106+
onCancelEdit() {
107+
this.setState({ isEditingRequest: false });
108+
}
109+
110+
onDraftChange(e) {
111+
this.setState({ draftRequest: e.target.value });
112+
}
113+
114+
async onResend() {
115+
const serviceUrl = this.props.selectedService || this.props.initialService;
116+
if (!serviceUrl) return;
117+
118+
let parsedRequest;
119+
try {
120+
parsedRequest = JSON.parse(this.state.draftRequest);
121+
} catch (e) {
122+
parsedRequest = this.state.draftRequest;
123+
}
124+
125+
try {
126+
const result = await axios({
127+
method: 'post',
128+
url: serviceUrl,
129+
data: parsedRequest,
130+
headers: {
131+
Accept: 'application/json',
132+
Authorization: `Bearer ${generateJWT(serviceUrl)}`,
133+
},
134+
});
135+
this.props.storeExchange(serviceUrl, parsedRequest, result.data, result.status);
136+
} catch (err) {
137+
const status = err.response ? err.response.status : 500;
138+
const response = err.response ? err.response.data : err.message;
139+
this.props.storeExchange(serviceUrl, parsedRequest, response, status);
140+
}
141+
142+
this.setState({ isEditingRequest: false });
143+
}
144+
83145
/**
84146
* Create an array of key-value pair objects that React Select component understands
85147
* given the CDS Services allowed to be selected for this hook
@@ -157,11 +219,32 @@ export class ContextView extends Component {
157219
}}
158220
/>
159221
</FormControl>
160-
<ExchangePanel
161-
panelHeader=" Request"
162-
panelText={serviceExchange ? serviceExchange.request : 'No request made to CDS Service'}
163-
isExpanded={false}
164-
/>
222+
{this.state.isEditingRequest ? (
223+
<div>
224+
<div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: '8px', gap: '8px' }}>
225+
<MuiButton variant="outlined" size="small" onClick={this.onCancelEdit}>Cancel</MuiButton>
226+
<MuiButton variant="contained" size="small" onClick={this.onResend}>Resend</MuiButton>
227+
</div>
228+
<textarea
229+
value={this.state.draftRequest}
230+
onChange={this.onDraftChange}
231+
className={styles['edit-textarea']}
232+
/>
233+
</div>
234+
) : (
235+
<div>
236+
<ExchangePanel
237+
panelHeader=" Request"
238+
panelText={serviceExchange ? serviceExchange.request : 'No request made to CDS Service'}
239+
isExpanded={false}
240+
/>
241+
{serviceExchange && serviceExchange.request && (
242+
<div style={{ textAlign: 'right', marginTop: '8px' }}>
243+
<MuiButton variant="outlined" size="small" onClick={this.onEditRequest}>Edit Request</MuiButton>
244+
</div>
245+
)}
246+
</div>
247+
)}
165248
<ExchangePanel
166249
panelHeader=" Response"
167250
panelText={serviceExchange ? serviceExchange.response : 'No response made to CDS Service'}
@@ -208,6 +291,9 @@ const mapDispatchToProps = (dispatch) => ({
208291
toggleContext: () => {
209292
dispatch(setContextVisibility());
210293
},
294+
storeExchange: (url, request, response, responseStatus) => {
295+
dispatch(storeExchange(url, request, response, responseStatus));
296+
},
211297
});
212298

213299
export default connect(mapStateToProps, mapDispatchToProps)(ContextView);

0 commit comments

Comments
 (0)