From 67750b61b74ed0158691a6f0d23a38ab9039ca35 Mon Sep 17 00:00:00 2001 From: Connor Turland Date: Wed, 25 Oct 2017 20:51:33 -0400 Subject: [PATCH] use redux and do this thing right --- frontend/src/Metamaps/GlobalUI/ReactApp.js | 12 +- frontend/src/Metamaps/Map/index.js | 2 +- frontend/src/actions/constants.js | 2 + frontend/src/actions/index.js | 13 ++ frontend/src/reducers/index.js | 9 ++ frontend/src/reducers/map/chat.js | 22 +++ frontend/src/reducers/map/contextMenu.js | 5 + frontend/src/reducers/map/createSynapse.js | 5 + frontend/src/reducers/map/createTopic.js | 5 + frontend/src/reducers/map/filters.js | 21 +++ frontend/src/reducers/map/importDialogue.js | 5 + frontend/src/reducers/map/index.js | 33 +++++ frontend/src/reducers/map/layout.js | 5 + frontend/src/reducers/map/metacodeSelect.js | 5 + frontend/src/reducers/map/mouse.js | 5 + frontend/src/reducers/map/realtime.js | 5 + frontend/src/reducers/map/selected.js | 8 ++ frontend/src/reducers/map/settings.js | 21 +++ frontend/src/reducers/map/synapseCard.js | 3 + frontend/src/reducers/map/topicCard.js | 3 + frontend/src/reducers/notifications/index.js | 3 + frontend/src/routes/MapView/MapView.js | 117 ++++++++++++++++ frontend/src/routes/MapView/index.js | 135 +------------------ frontend/src/routes/MapView/store.js | 23 ++++ package.json | 3 +- 25 files changed, 336 insertions(+), 134 deletions(-) create mode 100644 frontend/src/actions/constants.js create mode 100644 frontend/src/actions/index.js create mode 100644 frontend/src/reducers/index.js create mode 100644 frontend/src/reducers/map/chat.js create mode 100644 frontend/src/reducers/map/contextMenu.js create mode 100644 frontend/src/reducers/map/createSynapse.js create mode 100644 frontend/src/reducers/map/createTopic.js create mode 100644 frontend/src/reducers/map/filters.js create mode 100644 frontend/src/reducers/map/importDialogue.js create mode 100644 frontend/src/reducers/map/index.js create mode 100644 frontend/src/reducers/map/layout.js create mode 100644 frontend/src/reducers/map/metacodeSelect.js create mode 100644 frontend/src/reducers/map/mouse.js create mode 100644 frontend/src/reducers/map/realtime.js create mode 100644 frontend/src/reducers/map/selected.js create mode 100644 frontend/src/reducers/map/settings.js create mode 100644 frontend/src/reducers/map/synapseCard.js create mode 100644 frontend/src/reducers/map/topicCard.js create mode 100644 frontend/src/reducers/notifications/index.js create mode 100644 frontend/src/routes/MapView/MapView.js create mode 100644 frontend/src/routes/MapView/store.js diff --git a/frontend/src/Metamaps/GlobalUI/ReactApp.js b/frontend/src/Metamaps/GlobalUI/ReactApp.js index 7a744433..62b5c441 100644 --- a/frontend/src/Metamaps/GlobalUI/ReactApp.js +++ b/frontend/src/Metamaps/GlobalUI/ReactApp.js @@ -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) => - const app = + const app = + + ReactDOM.render(app, document.getElementById('react-app')) }, getProps: function() { diff --git a/frontend/src/Metamaps/Map/index.js b/frontend/src/Metamaps/Map/index.js index 43af6b2a..52271250 100644 --- a/frontend/src/Metamaps/Map/index.js +++ b/frontend/src/Metamaps/Map/index.js @@ -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' diff --git a/frontend/src/actions/constants.js b/frontend/src/actions/constants.js new file mode 100644 index 00000000..caa733c0 --- /dev/null +++ b/frontend/src/actions/constants.js @@ -0,0 +1,2 @@ +export const OPEN_CHAT = 'OPEN_CHAT' +export const CLOSE_CHAT = 'CLOSE_CHAT' diff --git a/frontend/src/actions/index.js b/frontend/src/actions/index.js new file mode 100644 index 00000000..37aa5f75 --- /dev/null +++ b/frontend/src/actions/index.js @@ -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 + } +} diff --git a/frontend/src/reducers/index.js b/frontend/src/reducers/index.js new file mode 100644 index 00000000..d0934fea --- /dev/null +++ b/frontend/src/reducers/index.js @@ -0,0 +1,9 @@ +import { combineReducers } from 'redux' + +import map from './map' +//import notifications from './notifications' + +export default combineReducers({ + map//, + //notifications +}) diff --git a/frontend/src/reducers/map/chat.js b/frontend/src/reducers/map/chat.js new file mode 100644 index 00000000..3bdd42af --- /dev/null +++ b/frontend/src/reducers/map/chat.js @@ -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 +} diff --git a/frontend/src/reducers/map/contextMenu.js b/frontend/src/reducers/map/contextMenu.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/contextMenu.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/createSynapse.js b/frontend/src/reducers/map/createSynapse.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/createSynapse.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/createTopic.js b/frontend/src/reducers/map/createTopic.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/createTopic.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/filters.js b/frontend/src/reducers/map/filters.js new file mode 100644 index 00000000..b0947a24 --- /dev/null +++ b/frontend/src/reducers/map/filters.js @@ -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 +} diff --git a/frontend/src/reducers/map/importDialogue.js b/frontend/src/reducers/map/importDialogue.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/importDialogue.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/index.js b/frontend/src/reducers/map/index.js new file mode 100644 index 00000000..7f993e69 --- /dev/null +++ b/frontend/src/reducers/map/index.js @@ -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 +}) diff --git a/frontend/src/reducers/map/layout.js b/frontend/src/reducers/map/layout.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/layout.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/metacodeSelect.js b/frontend/src/reducers/map/metacodeSelect.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/metacodeSelect.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/mouse.js b/frontend/src/reducers/map/mouse.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/mouse.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/realtime.js b/frontend/src/reducers/map/realtime.js new file mode 100644 index 00000000..d384069c --- /dev/null +++ b/frontend/src/reducers/map/realtime.js @@ -0,0 +1,5 @@ +const initialState = {} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/selected.js b/frontend/src/reducers/map/selected.js new file mode 100644 index 00000000..20e15a9d --- /dev/null +++ b/frontend/src/reducers/map/selected.js @@ -0,0 +1,8 @@ +const initialState = { + Nodes: [], + Edges: [] +} + +export default function (state = initialState, action) { + return state +} diff --git a/frontend/src/reducers/map/settings.js b/frontend/src/reducers/map/settings.js new file mode 100644 index 00000000..38d99394 --- /dev/null +++ b/frontend/src/reducers/map/settings.js @@ -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 +} diff --git a/frontend/src/reducers/map/synapseCard.js b/frontend/src/reducers/map/synapseCard.js new file mode 100644 index 00000000..27ce53b9 --- /dev/null +++ b/frontend/src/reducers/map/synapseCard.js @@ -0,0 +1,3 @@ +export default function (state = null, action) { + return state +} diff --git a/frontend/src/reducers/map/topicCard.js b/frontend/src/reducers/map/topicCard.js new file mode 100644 index 00000000..27ce53b9 --- /dev/null +++ b/frontend/src/reducers/map/topicCard.js @@ -0,0 +1,3 @@ +export default function (state = null, action) { + return state +} diff --git a/frontend/src/reducers/notifications/index.js b/frontend/src/reducers/notifications/index.js new file mode 100644 index 00000000..be390c35 --- /dev/null +++ b/frontend/src/reducers/notifications/index.js @@ -0,0 +1,3 @@ +export default function notifications(state = [], action) { + return state +} diff --git a/frontend/src/routes/MapView/MapView.js b/frontend/src/routes/MapView/MapView.js new file mode 100644 index 00000000..1c477e5e --- /dev/null +++ b/frontend/src/routes/MapView/MapView.js @@ -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
+ 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} /> + + {openTopic && } + {contextMenu && } + {currentUser && } + {currentUser && this.mapChat = x} />} + + +
+ } +} diff --git a/frontend/src/routes/MapView/index.js b/frontend/src/routes/MapView/index.js index 0c15448e..9905327a 100644 --- a/frontend/src/routes/MapView/index.js +++ b/frontend/src/routes/MapView/index.js @@ -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
- 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} /> - - {openTopic && } - {contextMenu && } - {currentUser && } - {currentUser && this.mapChat = x} />} - - -
- } -} +export default connect(mapStateToProps, mapDispatchToProps)(MapView) diff --git a/frontend/src/routes/MapView/store.js b/frontend/src/routes/MapView/store.js new file mode 100644 index 00000000..5527489c --- /dev/null +++ b/frontend/src/routes/MapView/store.js @@ -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()) + } + } +} diff --git a/package.json b/package.json index 5cece282..20c93c70 100644 --- a/package.json +++ b/package.json @@ -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",