mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-22 15:37:45 +00:00
add view all button, add dropdown for contentviews
This commit is contained in:
parent
bcc496527e
commit
34fe391afb
@ -65,6 +65,7 @@
|
||||
}
|
||||
|
||||
.view-options {
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import * as MetaViews from './ContentView/MetaViews'
|
||||
import ViewSelector from './ContentView/ViewSelector'
|
||||
import UploadContentButton from './ContentView/UploadContentButton'
|
||||
import DownloadContentButton from './ContentView/DownloadContentButton'
|
||||
import ShowFullContentButton from './ContentView/ShowFullContentButton'
|
||||
|
||||
import { setContentView, displayLarge, updateEdit } from '../ducks/ui/flow'
|
||||
|
||||
@ -19,7 +20,7 @@ ContentView.propTypes = {
|
||||
ContentView.isContentTooLarge = msg => msg.contentLength > 1024 * 1024 * (ContentViews.ViewImage.matches(msg) ? 10 : 0.2)
|
||||
|
||||
function ContentView(props) {
|
||||
const { flow, message, contentView, isDisplayLarge, displayLarge, uploadContent, onContentChange, readonly } = props
|
||||
const { flow, message, contentView, isDisplayLarge, displayLarge, uploadContent, onContentChange, readonly, contentViewDescription } = props
|
||||
|
||||
if (message.contentLength === 0 && readonly) {
|
||||
return <MetaViews.ContentEmpty {...props}/>
|
||||
@ -37,13 +38,15 @@ function ContentView(props) {
|
||||
return (
|
||||
<div className="contentview">
|
||||
<View flow={flow} message={message} contentView={contentView} readonly={readonly} onChange={onContentChange}/>
|
||||
|
||||
<div className="view-options text-center">
|
||||
<ShowFullContentButton/>
|
||||
<div className="view-options">
|
||||
<ViewSelector message={message}/>
|
||||
|
||||
<DownloadContentButton flow={flow} message={message}/>
|
||||
|
||||
<UploadContentButton uploadContent={uploadContent}/>
|
||||
|
||||
<span>{contentViewDescription}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@ -53,6 +56,7 @@ export default connect(
|
||||
state => ({
|
||||
contentView: state.ui.flow.contentView,
|
||||
isDisplayLarge: state.ui.flow.displayLarge,
|
||||
contentViewDescription: state.ui.flow.viewDescription
|
||||
}),
|
||||
{
|
||||
displayLarge,
|
||||
|
@ -1,4 +1,6 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import React, { PropTypes, Component } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { setContentViewDescription, setShowFullContent } from '../../ducks/ui/flow'
|
||||
import ContentLoader from './ContentLoader'
|
||||
import { MessageUtils } from '../../flow/utils'
|
||||
import CodeEditor from './CodeEditor'
|
||||
@ -27,32 +29,63 @@ function Edit({ content, onChange }) {
|
||||
}
|
||||
Edit = ContentLoader(Edit)
|
||||
|
||||
class ViewServer extends Component {
|
||||
constructor(props){
|
||||
super(props)
|
||||
this.maxLines = 80
|
||||
}
|
||||
|
||||
function ViewServer(props){
|
||||
const {content, contentView, message} = props
|
||||
let data = JSON.parse(content)
|
||||
componentWillMount(){
|
||||
this.setContentView(this.props)
|
||||
}
|
||||
componentWillReceiveProps(nextProps){
|
||||
this.setContentView(nextProps)
|
||||
}
|
||||
setContentView(props){
|
||||
try {
|
||||
this.data = JSON.parse(props.content)
|
||||
}catch(err) {
|
||||
this.data= {lines: [], description: err.message}
|
||||
}
|
||||
|
||||
return <div>
|
||||
{contentView != data.description &&
|
||||
<div className="alert alert-warning">{data.description}</div>
|
||||
}
|
||||
<pre>
|
||||
{data.lines.map((line, i) =>
|
||||
<div key={`line${i}`}>
|
||||
{line.map((tuple, j) =>
|
||||
<span key={`tuple${j}`} className={tuple[0]}>
|
||||
{tuple[1]}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</pre>
|
||||
props.setContentViewDescription(props.contentView != this.data.description ? this.data.description : '')
|
||||
|
||||
let isFullContentShown = this.data.lines.length < this.maxLines
|
||||
if (isFullContentShown) props.setShowFullContent(true)
|
||||
}
|
||||
render() {
|
||||
const {content, contentView, message} = this.props
|
||||
|
||||
let lines = this.props.showFullContent ? this.data.lines : this.data.lines.slice(0, this.maxLines)
|
||||
|
||||
return <div>
|
||||
<pre>
|
||||
{lines.map((line, i) =>
|
||||
<div key={`line${i}`}>
|
||||
{line.map((tuple, j) =>
|
||||
<span key={`tuple${j}`} className={tuple[0]}>
|
||||
{tuple[1]}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</pre>
|
||||
{ViewImage.matches(message) &&
|
||||
<ViewImage {...props} />
|
||||
<ViewImage {...this.props} />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ViewServer = ContentLoader(ViewServer)
|
||||
ViewServer = connect(
|
||||
state => ({
|
||||
showFullContent: state.ui.flow.showFullContent
|
||||
}),
|
||||
{
|
||||
setContentViewDescription,
|
||||
setShowFullContent
|
||||
}
|
||||
)(ContentLoader(ViewServer))
|
||||
|
||||
export { Edit, ViewServer, ViewImage }
|
||||
|
29
web/src/js/components/ContentView/ShowFullContentButton.jsx
Normal file
29
web/src/js/components/ContentView/ShowFullContentButton.jsx
Normal file
@ -0,0 +1,29 @@
|
||||
import React, { Component, PropTypes } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { render } from 'react-dom';
|
||||
import Button from '../common/Button';
|
||||
import { setShowFullContent } from '../../ducks/ui/flow'
|
||||
|
||||
|
||||
|
||||
ShowFullContentButton.propTypes = {
|
||||
setShowFullContent: PropTypes.func.isRequired,
|
||||
showFullContent: PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
function ShowFullContentButton ( {setShowFullContent, showFullContent} ){
|
||||
|
||||
return (
|
||||
!showFullContent && <Button isXs={true} onClick={() => setShowFullContent(true)} text="Show full content"/>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(
|
||||
state => ({
|
||||
showFullContent: state.ui.flow.showFullContent
|
||||
}),
|
||||
{
|
||||
setShowFullContent
|
||||
}
|
||||
)(ShowFullContentButton)
|
||||
|
@ -1,48 +1,82 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import React, { PropTypes, Component } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import { connect } from 'react-redux'
|
||||
import * as ContentViews from './ContentViews'
|
||||
import { setContentView } from "../../ducks/ui/flow";
|
||||
import { setContentView, setContentViewSelectorOpen } from "../../ducks/ui/flow";
|
||||
|
||||
|
||||
function ViewButton({ name, setContentView, children, activeView }) {
|
||||
function ViewItem({ name, setContentView, children }) {
|
||||
return (
|
||||
<button
|
||||
onClick={() => setContentView(name)}
|
||||
className={classnames('btn btn-default', { active: name === activeView })}>
|
||||
{children}
|
||||
</button>
|
||||
<li>
|
||||
<a href="#" onClick={() => setContentView(name)}>
|
||||
{children}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
ViewButton = connect(state => ({
|
||||
activeView: state.ui.flow.contentView
|
||||
}), {
|
||||
setContentView
|
||||
})(ViewButton)
|
||||
|
||||
|
||||
ViewSelector.propTypes = {
|
||||
message: PropTypes.object.isRequired,
|
||||
}
|
||||
function ViewSelector({contentViews, isEdit }) {
|
||||
let edit = ContentViews.Edit.displayName
|
||||
return (
|
||||
<div className="view-selector btn-group btn-group-xs">
|
||||
/*ViewSelector.propTypes = {
|
||||
contentViews: PropTypes.array.isRequired,
|
||||
activeView: PropTypes.string.isRequired,
|
||||
isEdit: PropTypes.bool.isRequired,
|
||||
isContentViewSelectorOpen: PropTypes.bool.isRequired,
|
||||
setContentViewSelectorOpen: PropTypes.func.isRequired
|
||||
}*/
|
||||
|
||||
{contentViews.map(name =>
|
||||
<ViewButton key={name} name={name}>{name.toLowerCase().replace('_', ' ')}</ViewButton>
|
||||
)}
|
||||
|
||||
{isEdit &&
|
||||
<ViewButton key={edit} name={edit}>{edit.toLowerCase()}</ViewButton>
|
||||
}
|
||||
class ViewSelector extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
this.close = this.close.bind(this)
|
||||
}
|
||||
close() {
|
||||
this.props.setContentViewSelectorOpen(false)
|
||||
document.removeEventListener('click', this.close)
|
||||
}
|
||||
|
||||
</div>
|
||||
)
|
||||
onDropdown(e){
|
||||
e.preventDefault()
|
||||
this.props.setContentViewSelectorOpen(!this.props.isContentViewSelectorOpen)
|
||||
document.addEventListener('click', this.close)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {contentViews, activeView, isEdit, isContentViewSelectorOpen, setContentViewSelectorOpen, setContentView} = this.props
|
||||
let edit = ContentViews.Edit.displayName
|
||||
|
||||
return (
|
||||
<div className={classnames('dropup pull-left', { open: isContentViewSelectorOpen })}>
|
||||
<a className="btn btn-default btn-xs"
|
||||
onClick={ e => this.onDropdown(e) }
|
||||
href="#">
|
||||
<b>View:</b> {activeView}<span className="caret"></span>
|
||||
</a>
|
||||
<ul className="dropdown-menu" role="menu">
|
||||
{contentViews.map(name =>
|
||||
<ViewItem key={name} setContentView={setContentView} name={name}>
|
||||
{name.toLowerCase().replace('_', ' ')}
|
||||
</ViewItem>
|
||||
)}
|
||||
{isEdit &&
|
||||
<ViewItem key={edit} setContentView={setContentView} name={edit}>
|
||||
{edit.toLowerCase()}
|
||||
</ViewItem>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect (
|
||||
state => ({
|
||||
contentViews: state.settings.contentViews,
|
||||
activeView: state.ui.flow.contentView,
|
||||
isEdit: !!state.ui.flow.modifiedFlow,
|
||||
}))(ViewSelector)
|
||||
isContentViewSelectorOpen: state.ui.flow.isContentViewSelectorOpen
|
||||
}), {
|
||||
setContentView,
|
||||
setContentViewSelectorOpen
|
||||
}
|
||||
)(ViewSelector)
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
Button.propTypes = {
|
||||
onClick: PropTypes.func.isRequired,
|
||||
@ -6,9 +7,9 @@ Button.propTypes = {
|
||||
icon: PropTypes.string
|
||||
}
|
||||
|
||||
export default function Button({ onClick, text, icon, disabled }) {
|
||||
export default function Button({ onClick, text, icon, disabled, isXs }) {
|
||||
return (
|
||||
<div className={"btn btn-default"}
|
||||
<div className={classnames('btn btn-default', { 'btn-xs': isXs})}
|
||||
onClick={onClick}
|
||||
disabled={disabled}>
|
||||
{icon && (<i className={"fa fa-fw " + icon}/> )}
|
||||
|
@ -3,16 +3,22 @@ import { getDiff } from "../../utils"
|
||||
|
||||
import _ from 'lodash'
|
||||
|
||||
export const SET_CONTENT_VIEW = 'UI_FLOWVIEW_SET_CONTENT_VIEW',
|
||||
DISPLAY_LARGE = 'UI_FLOWVIEW_DISPLAY_LARGE',
|
||||
SET_TAB = "UI_FLOWVIEW_SET_TAB",
|
||||
START_EDIT = 'UI_FLOWVIEW_START_EDIT',
|
||||
UPDATE_EDIT = 'UI_FLOWVIEW_UPDATE_EDIT',
|
||||
UPLOAD_CONTENT = 'UI_FLOWVIEW_UPLOAD_CONTENT'
|
||||
export const SET_CONTENT_VIEW = 'UI_FLOWVIEW_SET_CONTENT_VIEW',
|
||||
DISPLAY_LARGE = 'UI_FLOWVIEW_DISPLAY_LARGE',
|
||||
SET_TAB = "UI_FLOWVIEW_SET_TAB",
|
||||
START_EDIT = 'UI_FLOWVIEW_START_EDIT',
|
||||
UPDATE_EDIT = 'UI_FLOWVIEW_UPDATE_EDIT',
|
||||
UPLOAD_CONTENT = 'UI_FLOWVIEW_UPLOAD_CONTENT',
|
||||
SET_SHOW_FULL_CONTENT = 'UI_SET_SHOW_FULL_CONTENT',
|
||||
SET_CONTENT_VIEW_DESCRIPTION = "UI_SET_CONTENT_VIEW_DESCRIPTION",
|
||||
SET_CONTENT_VIEW_SELECTOR = "UI_SET_CONTENT_VIEW_SELECTOR"
|
||||
|
||||
|
||||
const defaultState = {
|
||||
displayLarge: false,
|
||||
contentViewDescription: '',
|
||||
showFullContent: false,
|
||||
isContentViewSelectorOpen: false,
|
||||
modifiedFlow: false,
|
||||
contentView: 'Auto',
|
||||
tab: 'request',
|
||||
@ -26,7 +32,8 @@ export default function reducer(state = defaultState, action) {
|
||||
return {
|
||||
...state,
|
||||
modifiedFlow: action.flow,
|
||||
contentView: 'Edit'
|
||||
contentView: 'Edit',
|
||||
showFullContent: true
|
||||
}
|
||||
|
||||
case UPDATE_EDIT:
|
||||
@ -40,7 +47,9 @@ export default function reducer(state = defaultState, action) {
|
||||
...state,
|
||||
modifiedFlow: false,
|
||||
displayLarge: false,
|
||||
contentView: (wasInEditMode ? 'Auto' : state.contentView)
|
||||
contentView: (wasInEditMode ? 'Auto' : state.contentView),
|
||||
viewDescription: '',
|
||||
showFullContent: false,
|
||||
}
|
||||
|
||||
case flowsActions.UPDATE:
|
||||
@ -52,24 +61,46 @@ export default function reducer(state = defaultState, action) {
|
||||
...state,
|
||||
modifiedFlow: false,
|
||||
displayLarge: false,
|
||||
contentView: (wasInEditMode ? 'Auto' : state.contentView)
|
||||
contentView: (wasInEditMode ? 'Auto' : state.contentView),
|
||||
viewDescription: '',
|
||||
showFullContent: false
|
||||
}
|
||||
} else {
|
||||
return state
|
||||
}
|
||||
|
||||
case SET_CONTENT_VIEW_DESCRIPTION:
|
||||
return {
|
||||
...state,
|
||||
viewDescription: action.description
|
||||
}
|
||||
|
||||
case SET_SHOW_FULL_CONTENT:
|
||||
return {
|
||||
...state,
|
||||
showFullContent: action.show
|
||||
}
|
||||
|
||||
|
||||
case SET_CONTENT_VIEW_SELECTOR:
|
||||
return {
|
||||
...state,
|
||||
isContentViewSelectorOpen: action.contentViewSelector
|
||||
}
|
||||
|
||||
case SET_TAB:
|
||||
return {
|
||||
...state,
|
||||
tab: action.tab,
|
||||
displayLarge: false,
|
||||
showFullContent: false
|
||||
}
|
||||
|
||||
case SET_CONTENT_VIEW:
|
||||
return {
|
||||
...state,
|
||||
contentView: action.contentView,
|
||||
showFullContent: action.contentView == 'Edit'
|
||||
}
|
||||
|
||||
case DISPLAY_LARGE:
|
||||
@ -102,6 +133,22 @@ export function updateEdit(update) {
|
||||
return { type: UPDATE_EDIT, update }
|
||||
}
|
||||
|
||||
export function setContentViewDescription(description) {
|
||||
return { type: SET_CONTENT_VIEW_DESCRIPTION, description }
|
||||
}
|
||||
|
||||
export function setShowFullContent(show) {
|
||||
return { type: SET_SHOW_FULL_CONTENT, show }
|
||||
}
|
||||
|
||||
export function setContentViewSelectorOpen(open){
|
||||
return {type: SET_CONTENT_VIEW_SELECTOR, contentViewSelector: open}
|
||||
}
|
||||
|
||||
export function updateEdit(update) {
|
||||
return { type: UPDATE_EDIT, update }
|
||||
}
|
||||
|
||||
export function stopEdit(flow, modifiedFlow) {
|
||||
let diff = getDiff(flow, modifiedFlow)
|
||||
return flowsActions.update(flow, diff)
|
||||
|
Loading…
Reference in New Issue
Block a user