add view all button, add dropdown for contentviews

This commit is contained in:
Clemens 2016-08-03 12:08:10 +02:00
parent bcc496527e
commit 34fe391afb
7 changed files with 213 additions and 64 deletions

View File

@ -65,6 +65,7 @@
}
.view-options {
margin-bottom: 10px;
margin-top: 10px;
}

View File

@ -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}/>
&nbsp;
<DownloadContentButton flow={flow} message={message}/>
&nbsp;
<UploadContentButton uploadContent={uploadContent}/>
&nbsp;
<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,

View File

@ -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 }

View 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)

View File

@ -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)

View File

@ -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}/> )}

View File

@ -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)