use redux and do this thing right

This commit is contained in:
Connor Turland 2017-10-25 20:51:33 -04:00
parent 12ef63b20d
commit 67750b61b7
25 changed files with 336 additions and 134 deletions

View file

@ -2,10 +2,13 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { Router, browserHistory } from 'react-router'
import { merge } from 'lodash'
import apply from 'async/apply'
import reducers from '../../reducers'
import { notifyUser } from './index.js'
import ImportDialog from './ImportDialog'
import Notifications from './Notifications'
@ -21,6 +24,11 @@ import Visualize from '../Visualize'
import makeRoutes from '../../routes/makeRoutes'
let routes
let store = createStore(
reducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
// 220 wide + 16 padding on both sides
const MAP_WIDTH = 252
const MOBILE_VIEW_BREAKPOINT = 504
@ -92,7 +100,9 @@ const ReactApp = {
render: function() {
const self = ReactApp
const createElement = (Component, props) => <Component {...props} {...self.getProps()}/>
const app = <Router createElement={createElement} routes={routes} history={browserHistory} onUpdate={self.handleUpdate} />
const app = <Provider store={store}>
<Router createElement={createElement} routes={routes} history={browserHistory} onUpdate={self.handleUpdate} />
</Provider>
ReactDOM.render(app, document.getElementById('react-app'))
},
getProps: function() {

View file

@ -1,7 +1,7 @@
/* global $ */
import outdent from 'outdent'
import { find as _find } from 'lodash'
import _, { find as _find } from 'lodash'
import { browserHistory } from 'react-router'
import Active from '../Active'

View file

@ -0,0 +1,2 @@
export const OPEN_CHAT = 'OPEN_CHAT'
export const CLOSE_CHAT = 'CLOSE_CHAT'

View file

@ -0,0 +1,13 @@
import * as constants from './constants'
export const openChat = () => {
return {
type: constants.OPEN_CHAT
}
}
export const closeChat = () => {
return {
type: constants.CLOSE_CHAT
}
}

View file

@ -0,0 +1,9 @@
import { combineReducers } from 'redux'
import map from './map'
//import notifications from './notifications'
export default combineReducers({
map//,
//notifications
})

View file

@ -0,0 +1,22 @@
import {
OPEN_CHAT,
CLOSE_CHAT
} from '../../actions/constants'
const initialState = {
isOpen: false
}
export default function (state = initialState, action) {
switch (action.type) {
case OPEN_CHAT:
return {
isOpen: true
}
case CLOSE_CHAT:
return {
isOpen: false
}
}
return state
}

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,21 @@
const initialState = {
dataForPresentation: {
metacodes: {},
mappers: {},
synapses: {}
},
filters: {
metacodes: [],
mappers: [],
synapses: []
},
visible: {
metacodes: [],
mappers: [],
synapses: []
}
}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,33 @@
import { combineReducers } from 'redux'
import filters from './filters'
import selected from './selected'
import chat from './chat'
import createTopic from './createTopic'
import createSynapse from './createSynapse'
import contextMenu from './contextMenu'
import topicCard from './topicCard'
import synapseCard from './synapseCard'
import realtime from './realtime'
import settings from './settings'
import importDialogue from './importDialogue'
import layout from './layout'
import mouse from './mouse'
import metacodeSelect from './metacodeSelect'
export default combineReducers({
chat,
filters,
selected,
createTopic,
createSynapse,
contextMenu,
topicCard,
synapseCard,
realtime,
settings,
importDialogue,
layout,
mouse,
metacodeSelect
})

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,5 @@
const initialState = {}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,8 @@
const initialState = {
Nodes: [],
Edges: []
}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,21 @@
const initialState = {
colors: {
background: '#344A58',
synapses: {
normal: '#888888',
hover: '#888888',
selected: '#FFFFFF'
},
topics: {
selected: '#FFFFFF'
},
labels: {
background: '#18202E',
text: '#DDD'
}
}
}
export default function (state = initialState, action) {
return state
}

View file

@ -0,0 +1,3 @@
export default function (state = null, action) {
return state
}

View file

@ -0,0 +1,3 @@
export default function (state = null, action) {
return state
}

View file

@ -0,0 +1,3 @@
export default function notifications(state = [], action) {
return state
}

View file

@ -0,0 +1,117 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ContextMenu from '../../components/ContextMenu'
import MapVis from '../../components/MapVis'
import UpperOptions from '../../components/UpperOptions'
import InfoAndHelp from '../../components/InfoAndHelp'
import Instructions from './Instructions'
import VisualizationControls from '../../components/VisualizationControls'
import MapChat from './MapChat'
import TopicCard from '../../components/TopicCard'
export default class MapView extends Component {
static propTypes = {
contextMenu: PropTypes.bool,
mobile: PropTypes.bool,
mapId: PropTypes.string,
map: PropTypes.object,
mapIsStarred: PropTypes.bool,
onMapStar: PropTypes.func,
onMapUnstar: PropTypes.func,
filterData: PropTypes.object,
allForFiltering: PropTypes.object,
visibleForFiltering: PropTypes.object,
toggleMetacode: PropTypes.func,
toggleMapper: PropTypes.func,
toggleSynapse: PropTypes.func,
filterAllMetacodes: PropTypes.func,
filterAllMappers: PropTypes.func,
filterAllSynapses: PropTypes.func,
toggleMapInfoBox: PropTypes.func,
infoBoxHtml: PropTypes.string,
currentUser: PropTypes.object,
endActiveMap: PropTypes.func,
launchNewMap: PropTypes.func,
openImportLightbox: PropTypes.func,
forkMap: PropTypes.func,
openHelpLightbox: PropTypes.func,
onZoomExtents: PropTypes.func,
onZoomIn: PropTypes.func,
onZoomOut: PropTypes.func,
hasLearnedTopicCreation: PropTypes.bool,
chatIsOpen: PropTypes.bool,
closeChat: PropTypes.func,
openChat: PropTypes.func
}
componentWillUnmount() {
this.endMap()
}
endMap() {
this.props.closeChat()
this.mapChat.reset()
this.upperOptions.reset()
this.props.endActiveMap()
}
componentDidUpdate(prevProps) {
const oldMapId = prevProps.mapId
const { mapId, launchNewMap } = this.props
if (!oldMapId && mapId) launchNewMap(mapId)
else if (oldMapId && mapId && oldMapId !== mapId) {
this.endMap()
launchNewMap(mapId)
}
else if (oldMapId && !mapId) this.endMap()
}
render = () => {
const { mobile, map, currentUser, closeChat, openChat, chatIsOpen,
toggleMapInfoBox, infoBoxHtml, allForFiltering, visibleForFiltering,
toggleMetacode, toggleMapper, toggleSynapse, filterAllMetacodes,
filterAllMappers, filterAllSynapses, filterData,
openImportLightbox, forkMap, openHelpLightbox,
mapIsStarred, onMapStar, onMapUnstar, openTopic,
onZoomExtents, onZoomIn, onZoomOut, hasLearnedTopicCreation,
contextMenu, DataModel } = this.props
const canEditMap = map && map.authorizeToEdit(currentUser)
// TODO: stop using {...this.props} and make explicit
return <div className="mapWrapper">
<UpperOptions ref={x => this.upperOptions = x}
map={map}
currentUser={currentUser}
onImportClick={openImportLightbox}
onForkClick={forkMap}
canEditMap={canEditMap}
filterData={filterData}
allForFiltering={allForFiltering}
visibleForFiltering={visibleForFiltering}
toggleMetacode={toggleMetacode}
toggleMapper={toggleMapper}
toggleSynapse={toggleSynapse}
filterAllMetacodes={filterAllMetacodes}
filterAllMappers={filterAllMappers}
filterAllSynapses={filterAllSynapses} />
<MapVis map={map} DataModel={DataModel} />
{openTopic && <TopicCard {...this.props} />}
{contextMenu && <ContextMenu {...this.props} />}
{currentUser && <Instructions mobile={mobile} hasLearnedTopicCreation={hasLearnedTopicCreation} />}
{currentUser && <MapChat {...this.props} onOpen={openChat} onClose={closeChat} chatOpen={chatIsOpen} ref={x => this.mapChat = x} />}
<VisualizationControls map={map}
onClickZoomExtents={onZoomExtents}
onClickZoomIn={onZoomIn}
onClickZoomOut={onZoomOut} />
<InfoAndHelp mapIsStarred={mapIsStarred}
currentUser={currentUser}
map={map}
onInfoClick={toggleMapInfoBox}
onMapStar={onMapStar}
onMapUnstar={onMapUnstar}
onHelpClick={openHelpLightbox}
infoBoxHtml={infoBoxHtml} />
</div>
}
}

View file

@ -1,132 +1,5 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { mapStateToProps, mapDispatchToProps } from './store'
import MapView from './MapView'
import ContextMenu from '../../components/ContextMenu'
import MapVis from '../../components/MapVis'
import UpperOptions from '../../components/UpperOptions'
import InfoAndHelp from '../../components/InfoAndHelp'
import Instructions from './Instructions'
import VisualizationControls from '../../components/VisualizationControls'
import MapChat from './MapChat'
import TopicCard from '../../components/TopicCard'
export default class MapView extends Component {
static propTypes = {
contextMenu: PropTypes.bool,
mobile: PropTypes.bool,
mapId: PropTypes.string,
map: PropTypes.object,
mapIsStarred: PropTypes.bool,
onMapStar: PropTypes.func,
onMapUnstar: PropTypes.func,
filterData: PropTypes.object,
allForFiltering: PropTypes.object,
visibleForFiltering: PropTypes.object,
toggleMetacode: PropTypes.func,
toggleMapper: PropTypes.func,
toggleSynapse: PropTypes.func,
filterAllMetacodes: PropTypes.func,
filterAllMappers: PropTypes.func,
filterAllSynapses: PropTypes.func,
toggleMapInfoBox: PropTypes.func,
infoBoxHtml: PropTypes.string,
currentUser: PropTypes.object,
endActiveMap: PropTypes.func,
launchNewMap: PropTypes.func,
openImportLightbox: PropTypes.func,
forkMap: PropTypes.func,
openHelpLightbox: PropTypes.func,
onZoomExtents: PropTypes.func,
onZoomIn: PropTypes.func,
onZoomOut: PropTypes.func,
hasLearnedTopicCreation: PropTypes.bool
}
constructor(props) {
super(props)
this.state = {
chatOpen: false
}
}
componentWillUnmount() {
this.endMap()
}
endMap() {
this.setState({
chatOpen: false
})
this.mapChat.reset()
this.upperOptions.reset()
this.props.endActiveMap()
}
componentDidUpdate(prevProps) {
const oldMapId = prevProps.mapId
const { mapId, launchNewMap } = this.props
if (!oldMapId && mapId) launchNewMap(mapId)
else if (oldMapId && mapId && oldMapId !== mapId) {
this.endMap()
launchNewMap(mapId)
}
else if (oldMapId && !mapId) this.endMap()
}
render = () => {
const { mobile, map, currentUser, onOpen, onClose,
toggleMapInfoBox, infoBoxHtml, allForFiltering, visibleForFiltering,
toggleMetacode, toggleMapper, toggleSynapse, filterAllMetacodes,
filterAllMappers, filterAllSynapses, filterData,
openImportLightbox, forkMap, openHelpLightbox,
mapIsStarred, onMapStar, onMapUnstar, openTopic,
onZoomExtents, onZoomIn, onZoomOut, hasLearnedTopicCreation,
contextMenu, DataModel } = this.props
const { chatOpen } = this.state
const onChatOpen = () => {
this.setState({chatOpen: true})
onOpen()
}
const onChatClose = () => {
this.setState({chatOpen: false})
onClose()
}
const canEditMap = map && map.authorizeToEdit(currentUser)
// TODO: stop using {...this.props} and make explicit
return <div className="mapWrapper">
<UpperOptions ref={x => this.upperOptions = x}
map={map}
currentUser={currentUser}
onImportClick={openImportLightbox}
onForkClick={forkMap}
canEditMap={canEditMap}
filterData={filterData}
allForFiltering={allForFiltering}
visibleForFiltering={visibleForFiltering}
toggleMetacode={toggleMetacode}
toggleMapper={toggleMapper}
toggleSynapse={toggleSynapse}
filterAllMetacodes={filterAllMetacodes}
filterAllMappers={filterAllMappers}
filterAllSynapses={filterAllSynapses} />
<MapVis map={map} DataModel={DataModel} />
{openTopic && <TopicCard {...this.props} />}
{contextMenu && <ContextMenu {...this.props} />}
{currentUser && <Instructions mobile={mobile} hasLearnedTopicCreation={hasLearnedTopicCreation} />}
{currentUser && <MapChat {...this.props} onOpen={onChatOpen} onClose={onChatClose} chatOpen={chatOpen} ref={x => this.mapChat = x} />}
<VisualizationControls map={map}
onClickZoomExtents={onZoomExtents}
onClickZoomIn={onZoomIn}
onClickZoomOut={onZoomOut} />
<InfoAndHelp mapIsStarred={mapIsStarred}
currentUser={currentUser}
map={map}
onInfoClick={toggleMapInfoBox}
onMapStar={onMapStar}
onMapUnstar={onMapUnstar}
onHelpClick={openHelpLightbox}
infoBoxHtml={infoBoxHtml} />
</div>
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MapView)

View file

@ -0,0 +1,23 @@
import {
closeChat,
openChat
} from '../../actions'
export const mapStateToProps = (state, ownProps) => {
return {
chatIsOpen: state.map.chat.isOpen
}
}
export const mapDispatchToProps = (dispatch, ownProps) => {
return {
openChat: () => {
ownProps.onOpen()
return dispatch(openChat())
},
closeChat: () => {
ownProps.onClose()
return dispatch(closeChat())
}
}
}

View file

@ -49,8 +49,9 @@
"react-draggable": "3.0.3",
"react-dropzone": "4.1.2",
"react-onclickoutside": "6.5.0",
"react-redux": "^5.0.6",
"react-router": "3.0.5",
"redux": "3.7.2",
"redux": "^3.7.2",
"riek": "1.1.0",
"simplewebrtc": "2.2.2",
"socket.io": "1.3.7",