Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fill textarea with response from backend #109

Merged
merged 30 commits into from
May 14, 2018
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4b598db
Setup redux-thunk, actions to fetch response on button click
amitmbee Apr 24, 2018
4efb204
Define action creators and reducer for data fetch success and failure
amitmbee Apr 24, 2018
5464d12
Modify reducer to store response data for each tabId and each request
amitmbee Apr 24, 2018
c3e3663
Use aliases, requestId instead of tabId
amitmbee Apr 30, 2018
2bcba47
Setup redux-thunk, actions to fetch response on button click
amitmbee Apr 24, 2018
b130936
Define action creators and reducer for data fetch success and failure
amitmbee Apr 24, 2018
52391ef
Modify reducer to store response data for each tabId and each request
amitmbee Apr 24, 2018
24c909a
Use aliases, requestId instead of tabId
amitmbee Apr 30, 2018
9910bec
Add key attr to force re-render of textarea after seting defaultValue…
amitmbee May 2, 2018
7c729be
Add key attr to force re-render of textarea after seting defaultValue…
amitmbee May 2, 2018
18a3836
Send axios request to fetch response with request-headers, Fix fetch …
amitmbee May 2, 2018
6c2b626
Specify proper TS types for mouseEvents
amitmbee May 2, 2018
ccf1a7b
Use a single value from store to update textarea defaultValue
amitmbee May 3, 2018
d8cf415
Use aliases to dispatch async actions instead of in the component
amitmbee May 3, 2018
e1318f2
Log whenever the compoent re-renders
amitmbee May 4, 2018
d8146e9
Send stringified data to the reducer instead of checking in the compo…
amitmbee May 7, 2018
32297e9
Empty the responseData and responseText values from store, before upd…
amitmbee May 7, 2018
b366eef
Style fetch response button
amitmbee May 8, 2018
e5ba3f1
Merge branch 'master' into Fill-textarea-with-response
amitmbee May 8, 2018
c4891d6
Update yarn lockfile
amitmbee May 8, 2018
4ff5509
Add bg-icon to fetch-response button
amitmbee May 9, 2018
28e2f3f
Show a error message if if axios returns a error for fetch call
amitmbee May 9, 2018
17c0717
Use fetch icon as bg within fetch response button
amitmbee May 9, 2018
06a161f
Remove used icons from images folder
amitmbee May 9, 2018
b8f6963
Update readme : Add credits to The Noun Project for the icons used
amitmbee May 9, 2018
41808b3
Display Attribution title in readme properly
amitmbee May 9, 2018
ceec4a8
Update Readme - Add fetch response section
amitmbee May 10, 2018
11d9ece
Remove un-needed package from actions.ts
amitmbee May 10, 2018
57c6999
Minify readme images
amitmbee May 11, 2018
04f8f6b
use icon only for fetch response button
revathskumar May 14, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion app/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as axios from 'axios'
//ACTION CONSTANTS
export const START_LISTENING = "START_LISTENING";
export const STOP_LISTENING = "STOP_LISTENING";
Expand All @@ -15,6 +16,9 @@ export const CONTENT_TYPE_CHANGE = "CONTENT_TYPE_CHANGE"
export const PAGINATION_CHANGE = "PAGINATION_CHANGE"
export const UPDATE_MESSAGE = "UPDATE_MESSAGE"
export const UPDATE_INTERCEPTOR_STATUS = "UPDATE_INTERCEPTOR_STATUS"
export const FETCH_DATA = "FETCH_DATA"
export const FETCH_DATA_SUCCESS = "FETCH_DATA_SUCCESS"
export const FETCH_DATA_FAILURE = "FETCH_DATA_FAILURE"

// Action Creators
export function startListening (enabledStatus:boolean){
Expand Down Expand Up @@ -58,4 +62,16 @@ export function sendMessageToUI(message:string){
}
export function updateInterceptorStatus(tabId:number, value:boolean){
return {type : UPDATE_INTERCEPTOR_STATUS, payload : {tabId, value}}
}
}
export function fetchResponse(url:string,method:string, requestId:number) {
return {
type: FETCH_DATA,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is suppose to be a async action right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

payload : {url, method, requestId}
}
}
export function fetchSuccess(data:object, requestId:number){
return {type: FETCH_DATA_SUCCESS, payload : {response : data.data, requestId } }
}
export function fetchFailure(error:object, requestId:number){
return {type : FETCH_DATA_FAILURE, payload : {error : error.data, requestId } }
}
197 changes: 105 additions & 92 deletions app/components/Intercept_Components/InterceptTextBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,103 +8,116 @@ export const InterceptTextBox = props => {
const responseTextValue = props.responseText[props.rowProps.checkbox.requestId] || defaultResponseText;
const statusCodeValue = props.statusCodes[props.rowProps.checkbox.requestId] || defaultStatusCode;
const contentTypeValue = props.contentType[props.rowProps.checkbox.requestId] || defaultContentType;
let textAreaValue = JSON.stringify(props.responseData[props.rowProps.checkbox.requestId]) ||responseTextValue

return (
<div className="grid-container form">
<div className="full-url">
<label htmlFor="">URL</label>
<a href={props.rowProps.checkbox.url} className="urlText">
{props.rowProps.checkbox.url}
</a>
return (
<div className="grid-container form">
<div className="full-url">
<label htmlFor="">URL</label>
<a href={props.rowProps.checkbox.url} className="urlText">
{props.rowProps.checkbox.url}
</a>
</div>
<div className="response">
<span className="fetch-responsetext" onClick={() => {
props.fetchResponse(props.rowProps.checkbox.url,props.rowProps.checkbox.method, props.rowProps.checkbox.requestId )
.then( () => {
textAreaValue = JSON.stringify(props.responseData[props.rowProps.checkbox.requestId]) ||responseTextValue
})
.catch( () => {
textAreaValue = JSON.stringify(props.responseData[props.rowProps.checkbox.requestId]) ||responseTextValue
})
}
}>X</span>
<label htmlFor="">Response Text</label>
<textarea
name="responseText"
className="responseText"
defaultValue={textAreaValue }
key={textAreaValue}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added key attr to force re-render of textarea if changing defaultValue after clicking the fetchResponse (X) button

//value={textAreaValue}
onChange={event => props.handleRespTextChange(event.target.value, props.rowProps.checkbox.requestId)}
/>
</div>
<div className="status">
<label htmlFor="">Select Status</label>
<select
value={statusCodeValue}
className="select-status"
onChange={event => {
props.handleStatusCodeChange(event.target.value, props.rowProps.checkbox.requestId);
}}
>
<option value="100">100 - Continue</option>
<option value="101">101 - Switching Protocols</option>
<option value="200">200 - OK</option>
<option value="201">201 - Created</option>
<option value="202">202 - Accepted</option>
<option value="203">203 - Non-Authoritative Information</option>
<option value="204">204 - No Content</option>
<option value="205">205 - Reset Content</option>
<option value="206">206 - Partial Content</option>
<option value="207">207 - Multi-Status</option>
<option value="300">300 - Multiple Choice</option>
<option value="301">301 - Moved Permenantly</option>
<option value="302">302 - Found</option>
<option value="303">303 - See Other</option>
<option value="304">304 - Not Modified</option>
<option value="305">305 - Use Proxy</option>
<option value="307">307 - Temporary Redirect</option>
<option value="400">400 - Bad Request</option>
<option value="401">401 - Unauthorized</option>
<option value="402">402 - Payment Required</option>
<option value="403">403 - Forbidden</option>
<option value="404">404 - Not Found</option>
<option value="405">405 - Method Not Allowed</option>
<option value="406">406 - Not Acceptable</option>
<option value="407">407 - Proxy Authentication Required</option>
<option value="408">408 - Request Timeout</option>
<option value="409">409 - Conflict</option>
<option value="410">410 - Gone</option>
<option value="411">411 - Length Required</option>
<option value="412">412 - Precondition Failed</option>
<option value="413">413 - Request Entity Too Large</option>
<option value="414">414 - Request-URI Too Long</option>
<option value="415">415 - Unsupported Media Type</option>
<option value="416">416 - Requested Range Not Satisfiable</option>
<option value="417">417 - Expectation Failed</option>
<option value="422">422 - Unprocessable Entity</option>
<option value="500">500 - Internal Server Error</option>
<option value="501">501 - Not Implemented</option>
<option value="502">502 - Bad Gateway</option>
<option value="503">503 - Service Unavailable</option>
<option value="504">504 - Gateway Timeout</option>
<option value="505">505 - HTTP Version Not Supported</option>
</select>
</div>
<div className="content">
<label htmlFor="">Content Type</label>
<select
value={contentTypeValue}
className="content-type-select"
onChange={event => {
props.handleContentTypeChange(event.target.value, props.rowProps.checkbox.requestId);
}}
>
<option value="application/json">application/json</option>
<option value="text/html">text/html</option>
<option value="text/csv">text/csv</option>
<option value="application/javascript">application/javascript</option>
<option value="text/css">text/css</option>
<option value="text/plain">text/plain</option>
<option value="application/pdf">application/pdf</option>
</select>
</div>
<RequestHeaderList requestHeaders={props.rowProps.checkbox.requestHeaders} />
</div>
<div className="response">
<label htmlFor="">Response Text</label>
<textarea
name="responseText"
className="responseText"
defaultValue={responseTextValue}
//value={responseTextValue}
onChange={event => props.handleRespTextChange(event.target.value, props.rowProps.checkbox.requestId)}
/>
</div>
<div className="status">
<label htmlFor="">Select Status</label>
<select
value={statusCodeValue}
className="select-status"
onChange={event => {
props.handleStatusCodeChange(event.target.value, props.rowProps.checkbox.requestId);
}}
>
<option value="100">100 - Continue</option>
<option value="101">101 - Switching Protocols</option>
<option value="200">200 - OK</option>
<option value="201">201 - Created</option>
<option value="202">202 - Accepted</option>
<option value="203">203 - Non-Authoritative Information</option>
<option value="204">204 - No Content</option>
<option value="205">205 - Reset Content</option>
<option value="206">206 - Partial Content</option>
<option value="207">207 - Multi-Status</option>
<option value="300">300 - Multiple Choice</option>
<option value="301">301 - Moved Permenantly</option>
<option value="302">302 - Found</option>
<option value="303">303 - See Other</option>
<option value="304">304 - Not Modified</option>
<option value="305">305 - Use Proxy</option>
<option value="307">307 - Temporary Redirect</option>
<option value="400">400 - Bad Request</option>
<option value="401">401 - Unauthorized</option>
<option value="402">402 - Payment Required</option>
<option value="403">403 - Forbidden</option>
<option value="404">404 - Not Found</option>
<option value="405">405 - Method Not Allowed</option>
<option value="406">406 - Not Acceptable</option>
<option value="407">407 - Proxy Authentication Required</option>
<option value="408">408 - Request Timeout</option>
<option value="409">409 - Conflict</option>
<option value="410">410 - Gone</option>
<option value="411">411 - Length Required</option>
<option value="412">412 - Precondition Failed</option>
<option value="413">413 - Request Entity Too Large</option>
<option value="414">414 - Request-URI Too Long</option>
<option value="415">415 - Unsupported Media Type</option>
<option value="416">416 - Requested Range Not Satisfiable</option>
<option value="417">417 - Expectation Failed</option>
<option value="422">422 - Unprocessable Entity</option>
<option value="500">500 - Internal Server Error</option>
<option value="501">501 - Not Implemented</option>
<option value="502">502 - Bad Gateway</option>
<option value="503">503 - Service Unavailable</option>
<option value="504">504 - Gateway Timeout</option>
<option value="505">505 - HTTP Version Not Supported</option>
</select>
</div>
<div className="content">
<label htmlFor="">Content Type</label>
<select
value={contentTypeValue}
className="content-type-select"
onChange={event => {
props.handleContentTypeChange(event.target.value, props.rowProps.checkbox.requestId);
}}
>
<option value="application/json">application/json</option>
<option value="text/html">text/html</option>
<option value="text/csv">text/csv</option>
<option value="application/javascript">application/javascript</option>
<option value="text/css">text/css</option>
<option value="text/plain">text/plain</option>
<option value="application/pdf">application/pdf</option>
</select>
</div>
<RequestHeaderList requestHeaders={props.rowProps.checkbox.requestHeaders} />
</div>
);
);
};

InterceptTextBox.defaultProps = {
responseText: [],
statusCodes: [],
contentType: []
contentType: [],
responseData:{}
};
3 changes: 3 additions & 0 deletions app/components/Intercept_Components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export const InterceptForm = props => {
statusCodes={props.statusCodes}
handleContentTypeChange={props.handleContentTypeChange}
contentType={props.contentType}
tabId={props.tabId}
fetchResponse={props.fetchResponse}
responseData={props.responseData}
/>
</div>
);
Expand Down
5 changes: 5 additions & 0 deletions app/components/request_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface RequestObj {
disableInterceptor:React.ChangeEvent<HTMLButtonElement>;
updateInterceptorStatus:React.ChangeEvent<HTMLButtonElement>;
isInterceptorOn:object;
fetchResponse:React.MouseEvent<HTMLButtonElement>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come this is React.MouseEvent ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since fetchResponse is defined on onClick event, it is supposed to be React.MouseEvent i feel. Ref :https://reactjs.org/docs/events.html#mouse-events

responseData : object;
}
const RequestList = (props: RequestObj) => {
const columns = [
Expand Down Expand Up @@ -126,6 +128,9 @@ const RequestList = (props: RequestObj) => {
statusCodes={props.statusCodes}
handleContentTypeChange={props.handleContentTypeChange}
contentType={props.contentType}
tabId={props.tabId}
fetchResponse={props.fetchResponse}
responseData = {props.responseData}
/>
)}
/>
Expand Down
18 changes: 15 additions & 3 deletions app/containers/popup.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from "react";
import * as cx from "classnames";
import {connect} from "react-redux";
import {Store} from "react-chrome-redux";

import * as MessageService from "./../message_service";
import RequestList from "./../components/request_list";
Expand All @@ -20,7 +21,8 @@ interface DispatchProps {
handleStatusCodeChange: typeof actionTypes.handleStatusCodeChange;
handleContentTypeChange: typeof actionTypes.handleContentTypeChange;
handlePaginationChange: typeof actionTypes.handlePaginationChange;
updateInterceptorStatus: typeof actionTypes.updateInterceptorStatus
updateInterceptorStatus: typeof actionTypes.updateInterceptorStatus;
fetchResponse:typeof actionTypes.fetchResponse;
}

const CHROME_URL_REGEX = /^chrome:\/\/.+$/;
Expand All @@ -29,6 +31,12 @@ const isChromeUrl = (url: string) => {
return CHROME_URL_REGEX.test(url);
};

interface BgStore {
ready(): Promise<void>;
getState(): any;
dispatch: any;
}

export class Popup extends React.Component<POPUP_PROPS & DispatchProps, {}> {
componentWillMount() {
this.props.updateField("interceptStatus", "");
Expand Down Expand Up @@ -192,6 +200,8 @@ export class Popup extends React.Component<POPUP_PROPS & DispatchProps, {}> {
updateInterceptorStatus={this.updateInterceptorStatus}
isInterceptorOn={this.props.isInterceptorOn}
handleSwitch={this.handleSwitch}
fetchResponse={this.props.fetchResponse}
responseData={this.props.responseData}
/>
</div>
</div>
Expand All @@ -209,7 +219,8 @@ const mapStateToProps = (state: POPUP_PROPS) => ({
contentType: state.contentType,
PageDetails: state.PageDetails,
interceptStatus: state.interceptStatus,
isInterceptorOn: state.isInterceptorOn
isInterceptorOn: state.isInterceptorOn,
responseData: state.responseData
});

const mapDispatchToProps: DispatchProps = {
Expand All @@ -225,7 +236,8 @@ const mapDispatchToProps: DispatchProps = {
handleRespTextChange: actionTypes.handleRespTextChange,
handleContentTypeChange: actionTypes.handleContentTypeChange,
handlePaginationChange: actionTypes.handlePaginationChange,
updateInterceptorStatus: actionTypes.updateInterceptorStatus
updateInterceptorStatus: actionTypes.updateInterceptorStatus,
fetchResponse:actionTypes.fetchResponse
};

export default connect(mapStateToProps, mapDispatchToProps)(Popup);
19 changes: 16 additions & 3 deletions app/reducers/rootReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export const INITIAL_POPUP_STATE: POPUP_PROPS = {
contentType: {},
PageDetails: {},
interceptStatus : "",
isInterceptorOn: {}
isInterceptorOn: {},
responseData : {}
};

//ACTION CONSTANTS
Expand Down Expand Up @@ -61,14 +62,26 @@ export const reducer = (state = INITIAL_POPUP_STATE, action: Action) => {
}
}
};
case actionType.UPDATE_MESSAGE:{
case actionType.UPDATE_MESSAGE:{
return {...state, interceptStatus : action.message }
}
case actionType.UPDATE_INTERCEPTOR_STATUS:
case actionType.UPDATE_INTERCEPTOR_STATUS:
return {
...state,
isInterceptorOn: {...state.isInterceptorOn, [action.payload.tabId]: action.payload.value}
};
case actionType.FETCH_DATA_SUCCESS: {
return {
...state,
responseData: {...state.responseData, [action.payload.requestId]: action.payload.response}
};
}
case actionType.FETCH_DATA_FAILURE: {
return {
...state,
responseData: {...state.responseData, [action.payload.requestId]: action.payload.error}
};
}
default:
return state;
}
Expand Down
24 changes: 24 additions & 0 deletions app/store/aliases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as axios from 'axios'
import { fetchResponse, fetchSuccess, fetchFailure } from './../actions'

const fetchDataAlias = ({payload}) => {
return (dispatch, getState) => {
const {method, url, requestId} = payload
console.log(method, url, requestId)
//dispatch(fetchResponse(payload.url, payload.method, payload.tabId))
axios({
method,
url
})
.then( (data) => {
dispatch(fetchSuccess(data, requestId))
})
.catch( (err) => {
dispatch(fetchFailure(err, requestId))
})
}
}

export default {
"FETCH_DATA": fetchDataAlias
}
Loading