Browse Source

added message system

Tomi Cvetic 7 năm trước cách đây
mục cha
commit
f9468e5a1d

+ 13 - 12
src/Main.js

@@ -1,31 +1,32 @@
 import React from 'react'           // React to manage the GUI
 
 /** Import sub-modules */
-import startPage from './startPage'
-import playerList from './playerList'       // Everything that has to do with players
-import matchList from './matchList'         // Everything that has to do with matches
-import layout from './layout'
+import StartPage from './startPage/components/StartPage'
+import PlayerList from './playerList/components/PlayerList'       // Everything that has to do with players
+import MatchTable from './matchList/components/MatchTable'         // Everything that has to do with matches
+import AppLayout from './layout/components/AppLayout'
+import AlertList from './alerts/components/AlertList'
 
 /** Import CSS Styles */
-import 'bootstrap/dist/css/bootstrap.css'
+import 'bootstrap/dist/css/bootstrap.min.css'
+import './App.css'
+
+// console.log(layout)
 
 /** Main application */
 class Main extends React.Component {
   render () {
-    const AppLayout = layout.components.AppLayout
-
     return (
       <div className='container'>
         <AppLayout
-          layout={this.props.layout}
-          layoutActions={this.props.layoutActions}
           state={this.props}
           components={{
-            PlayerList: playerList.components.PlayerList,
-            MatchTable: matchList.components.MatchTable,
-            StartPage: startPage.components.StartPage
+            PlayerList,
+            MatchTable,
+            StartPage
           }}
         />
+        <AlertList alerts={this.props.alerts} alertsActions={this.props.alertsActions} />
       </div>
     )
   }

+ 53 - 0
src/alerts/components/AlertList.js

@@ -0,0 +1,53 @@
+import React from 'react'
+import { Alert } from 'react-bootstrap'
+
+class AlertView extends React.Component {
+  constructor () {
+    super()
+    this.handleDismiss = this.handleDismiss.bind(this)
+  }
+
+  handleDismiss (event) {
+    event.preventDefault()
+    const { alertDismiss, index } = this.props
+    alertDismiss(index)
+  }
+
+  render () {
+    const { alert } = this.props
+    let alertIcon = ''
+    if (alert.type === 'info') {
+      alertIcon = 'glyphicon glyphicon-info-sign'
+    }
+    if (alert.type === 'warning' || alert.type === 'danger') {
+      alertIcon = 'glyphicon glyphicon-remove-sign'
+    }
+    if (alert.type === 'success') {
+      alertIcon = 'glyphicon glyphicon-ok-sign'
+    }
+    return (
+      <Alert bsStyle={alert.type} onDismiss={this.handleDismiss}>
+        <p><span className={alertIcon} /> {alert.text}</p>
+      </Alert>
+    )
+  }
+}
+
+class AlertList extends React.Component {
+  render () {
+    const { alerts } = this.props.alerts
+    const { alertDismiss } = this.props.alertsActions
+
+    if (alerts.length > 0) {
+      return (
+        <div className='alert-list'>
+          {alerts.map((alert, key) => <AlertView key={key} index={key} alert={alert} alertDismiss={alertDismiss} />)}
+        </div>
+      )
+    } else {
+      return null
+    }
+  }
+}
+
+export default AlertList

+ 3 - 0
src/alerts/components/index.js

@@ -0,0 +1,3 @@
+import AlertList from './AlertList'
+
+export default { AlertList }

+ 8 - 0
src/alerts/index.js

@@ -0,0 +1,8 @@
+import { actions, reducer, state, saga } from './state'
+import components from './components'
+
+const filters = {}
+
+const selectors = {}
+
+export default { actions, components, filters, selectors, reducer, state, saga }

+ 46 - 0
src/alerts/state.js

@@ -0,0 +1,46 @@
+/** @module player/state */
+// import { call, put, takeEvery, takeLatest } from 'redux-saga/effects'
+
+/**
+ * state.js
+ *
+ * Collection of everything which has to do with state changes.
+ **/
+
+/** actionTypes define what actions are handeled by the reducer. */
+export const actions = {
+  alertAdd: alert => {
+    return {
+      type: 'ALERT_ADD',
+      alert
+    }
+  },
+  alertDismiss: alertId => {
+    return {
+      type: 'ALERT_DISMISS',
+      alertId
+    }
+  }
+}
+console.log('State actions', actions)
+
+/** state definition */
+export const state = {
+  alerts: []
+}
+console.log('State state', state)
+
+/** reducer is called by the redux dispatcher and handles all component actions */
+export function reducer (state = [], action) {
+  switch (action.type) {
+    case 'ALERT_ADD':
+      return { ...state, alerts: [ ...state.alerts, action.alert ] }
+    case 'ALERT_DISMISS':
+      return { ...state, alerts: [ ...state.alerts.slice(0, action.alertId), ...state.alerts.slice(action.alertId + 1) ] }
+    default:
+      return state
+  }
+}
+
+/** sagas are asynchronous workers (JS generators) to handle the state. */
+export function * saga () {}

+ 36 - 10
src/index.js

@@ -3,8 +3,11 @@
 // Import dependencies
 import React from 'react'
 import ReactDOM from 'react-dom'
-import { createStore, combineReducers, bindActionCreators, compose } from 'redux'
+import { createStore, applyMiddleware, combineReducers, bindActionCreators, compose } from 'redux'
 import { Provider, connect } from 'react-redux'
+import createSagaMiddleware from 'redux-saga'
+import { all } from 'redux-saga/effects'
+
 /** react-router is not used in this project.
 import { browserHistory, Router, Route, IndexRoute } from 'react-router'
 import { syncHistoryWithStore, routerReducer } from 'react-router-redux'
@@ -14,8 +17,10 @@ import { syncHistoryWithStore, routerReducer } from 'react-router-redux'
 import Main from './Main'
 
 // Import the submodules
-import player from './player'
-import match from './match'
+import playerList from './playerList'
+import matchList from './matchList'
+import layout from './layout'
+import alerts from './alerts'
 
 /**
  * Redux Section
@@ -23,26 +28,46 @@ import match from './match'
 
 /** The root reducer is combined from all sub-module reducers */
 const rootReducer = combineReducers({
-  player: player.reducer,
-  match: match.reducer
+  playerList: playerList.reducer,
+  matchList: matchList.reducer,
+  layout: layout.reducer,
+  alerts: alerts.reducer
 })
 console.log('Root reducer:', rootReducer)
 
 /** The default state is combined from all sub-module states */
 const defaultState = {
-  player: player.state,
-  match: match.state
+  playerList: playerList.state,
+  matchList: matchList.state,
+  layout: layout.state,
+  alerts: alerts.state
 }
 console.log('Default state:', defaultState)
 
+/** The root saga, calling all other sagas */
+function * rootSaga () {
+  console.log('rootSaga called')
+  yield all([
+    playerList.saga(),
+    matchList.saga(),
+    layout.saga(),
+    alerts.saga()
+  ])
+}
+
+/** Create the saga middleware */
+const sagaMiddleware = createSagaMiddleware()
+
 /** The enhancer allows to use Redux development tools in Chrome */
 const enhancers = compose(
+  applyMiddleware(sagaMiddleware),
   window.devToolsExtension ? window.devToolsExtension() : f => f
 )
 console.log('Enhancers:', enhancers)
 
 /** Build the Redux store from the rootReducer, the defualtState and the enhancers. */
 const store = createStore(rootReducer, defaultState, enhancers)
+sagaMiddleware.run(rootSaga)
 console.log('Store:', store)
 /** react-route is not used in this project.
 const history = syncHistoryWithStore(browserHistory, store)
@@ -51,8 +76,10 @@ console.log('history:', history)
 
 /** Collect the action creators from all modules in actionCreators */
 const actionCreators = {
-  player: player.actions,
-  match: match.actions
+  playerList: playerList.actions,
+  matchList: matchList.actions,
+  layout: layout.actions,
+  alerts: alerts.actions
 }
 
 /** Creates a function  */
@@ -101,7 +128,6 @@ const router = (
   </Provider>
 )
 */
-
 const provider = (
   <Provider store={store}>
     <App />

+ 11 - 6
src/layout/components/AppLayout.js

@@ -3,18 +3,23 @@ import { Tabs, Tab } from 'react-bootstrap'
 
 class AppLayout extends React.Component {
   render () {
-    console.log('AppLayout state', this.props.state)
-    const { activeTab } = this.props.layout
-    const { changeTab } = this.props.layoutActions
     const { state } = this.props
+    const { activeTab } = this.props.state.layout
+    const { changeTab } = this.props.state.layoutActions
     const { PlayerList, MatchTable, StartPage } = this.props.components
 
     return (
       <div>
         <Tabs activeKey={activeTab} onSelect={changeTab} id='layout-tabs'>
-          <Tab eventKey={0} title='Setup'><StartPage state={state.setupPage} actions={state.setupPageActions} /></Tab>
-          <Tab eventKey={1} title='PlayerList' disabled><PlayerList state={state.playerList} actions={state.playerListActions} /></Tab>
-          <Tab eventKey={2} title='Calendar' disabled><MatchTable state={state.matchList} actions={state.matchListActions} /></Tab>
+          <Tab eventKey={0} title='Setup'>
+            <StartPage state={state.setupPage} actions={state.setupPageActions} />
+          </Tab>
+          <Tab eventKey={1} title='PlayerList' disabled>
+            <PlayerList state={state.playerList} actions={state.playerListActions} />
+          </Tab>
+          <Tab eventKey={2} title='Calendar' disabled>
+            <MatchTable state={state.matchList} actions={state.matchListActions} />
+          </Tab>
           <Tab eventKey={3} title='Spielplan' disabled />
           <Tab eventKey={4} title='Zahlliste' disabled />
         </Tabs>

+ 16 - 6
src/startPage/components/FileImport.js

@@ -44,15 +44,26 @@ class FileButton extends React.Component {
   }
 
   processFile (ev) {
-    console.log(`process file`)
     this.file = this.fileName.files[0]
+    console.log(`process file`, this.file)
   }
 
   render () {
     return (
       <div className='file-button'>
-        <input name={this.props.name} id={this.props.name} ref={input => this.fileName = input} type='file' style={this.inputStyle} props={this.props} onChange={this.processFile} />
-        <label htmlFor={this.props.name} onMouseEnter={this.getFocus} onMouseLeave={this.loseFocus} style={this.labelStyle}><span className='glyphicon glyphicon-open' ariaHidden='true' /> PlayerList.xls laden...</label>
+        <input
+          name={this.props.name}
+          id={this.props.name}
+          ref={input => this.fileName = input}
+          type='file' style={this.inputStyle}
+          onChange={this.processFile} />
+        <label
+          htmlFor={this.props.name}
+          onMouseEnter={this.getFocus}
+          onMouseLeave={this.loseFocus}
+          style={this.labelStyle}>
+          <span className='glyphicon glyphicon-open' /> {this.props.children}
+        </label>
         {this.file ? <span>{this.file.name}<i>{fileSize(this.file.size)}</i> not boring</span> : <span>boring</span>}
       </div>
     )
@@ -79,9 +90,8 @@ class FileImport extends React.Component {
   render () {
     return (
       <div>
-        <Button onClick={this.handlePlayerList}>PlayerList.xls</Button>
-        <Button onClick={this.handleCalendar}>Calendar.xls</Button>
-        <FileButton name='playerList' data-allowed-file-extensions='xls' />
+        <FileButton name='playerList' data-allowed-file-extensions='xls'>PlayerList.xls laden...</FileButton>
+        <FileButton name='calendar' data-allowed-file-extensions='xls'>Calendar.xls laden...</FileButton>
       </div>
     )
   }

+ 3 - 22
src/startPage/state.js

@@ -1,4 +1,5 @@
 /** @module setting/state */
+// import { takeEvery } from 'redux-saga/effects'
 
 /**
  * state.js
@@ -7,36 +8,16 @@
  **/
 
 /** actionTypes define what actions are handeled by the reducer. */
-export const actions = {
-  changePriceAdult: priceAdult => {
-    return {
-      type: 'SETTING_CHANGE_PRICE_ADULT',
-      priceAdult
-    }
-  },
-  changePriceJunior: priceJunior => {
-    return {
-      type: 'SETTING_CHANGE_PRICE_JUNIOR',
-      priceJunior
-    }
-  }
-}
+export const actions = {}
 console.log('State actions', actions)
 
 /** state definition */
-export const state = {
-  priceAdult: 50,
-  priceJunior: 30
-}
+export const state = {}
 console.log('State state', state)
 
 /** reducer is called by the redux dispatcher and handles all component actions */
 export function reducer (state = [], action) {
   switch (action.type) {
-    case 'SETTING_CHANGE_PRICE_ADULT':
-      return { ...state, priceAdult: action.priceAdult }
-    case 'SETTING_CHANGE_PRICE_JUNIOR':
-      return { ...state, priceJunior: action.priceJunior }
     default:
       return state
   }