From b6f08e58fae35d5dd8a610af31c2950b37746695 Mon Sep 17 00:00:00 2001
From: cedricnjanga
Date: Fri, 6 Oct 2017 10:17:17 +0200
Subject: Add webpacker gem and migrate the React apps
---
app/javascript/journey_patterns/actions/index.js | 220 +++++++++++++++++++++
app/javascript/journey_patterns/components/App.js | 21 ++
.../journey_patterns/components/ConfirmModal.js | 46 +++++
.../journey_patterns/components/CreateModal.js | 122 ++++++++++++
.../journey_patterns/components/EditModal.js | 110 +++++++++++
.../journey_patterns/components/JourneyPattern.js | 131 ++++++++++++
.../journey_patterns/components/JourneyPatterns.js | 155 +++++++++++++++
.../journey_patterns/components/Navigate.js | 62 ++++++
.../components/SaveJourneyPattern.js | 39 ++++
.../containers/AddJourneyPattern.js | 30 +++
.../journey_patterns/containers/ConfirmModal.js | 30 +++
.../containers/JourneyPatternList.js | 34 ++++
.../journey_patterns/containers/Modal.js | 26 +++
.../journey_patterns/containers/Navigate.js | 15 ++
.../containers/SaveJourneyPattern.js | 27 +++
.../journey_patterns/reducers/editMode.js | 10 +
app/javascript/journey_patterns/reducers/index.js | 18 ++
.../journey_patterns/reducers/journeyPatterns.js | 90 +++++++++
app/javascript/journey_patterns/reducers/modal.js | 41 ++++
.../journey_patterns/reducers/pagination.js | 35 ++++
app/javascript/journey_patterns/reducers/status.js | 21 ++
.../journey_patterns/reducers/stopPointsList.js | 6 +
22 files changed, 1289 insertions(+)
create mode 100644 app/javascript/journey_patterns/actions/index.js
create mode 100644 app/javascript/journey_patterns/components/App.js
create mode 100644 app/javascript/journey_patterns/components/ConfirmModal.js
create mode 100644 app/javascript/journey_patterns/components/CreateModal.js
create mode 100644 app/javascript/journey_patterns/components/EditModal.js
create mode 100644 app/javascript/journey_patterns/components/JourneyPattern.js
create mode 100644 app/javascript/journey_patterns/components/JourneyPatterns.js
create mode 100644 app/javascript/journey_patterns/components/Navigate.js
create mode 100644 app/javascript/journey_patterns/components/SaveJourneyPattern.js
create mode 100644 app/javascript/journey_patterns/containers/AddJourneyPattern.js
create mode 100644 app/javascript/journey_patterns/containers/ConfirmModal.js
create mode 100644 app/javascript/journey_patterns/containers/JourneyPatternList.js
create mode 100644 app/javascript/journey_patterns/containers/Modal.js
create mode 100644 app/javascript/journey_patterns/containers/Navigate.js
create mode 100644 app/javascript/journey_patterns/containers/SaveJourneyPattern.js
create mode 100644 app/javascript/journey_patterns/reducers/editMode.js
create mode 100644 app/javascript/journey_patterns/reducers/index.js
create mode 100644 app/javascript/journey_patterns/reducers/journeyPatterns.js
create mode 100644 app/javascript/journey_patterns/reducers/modal.js
create mode 100644 app/javascript/journey_patterns/reducers/pagination.js
create mode 100644 app/javascript/journey_patterns/reducers/status.js
create mode 100644 app/javascript/journey_patterns/reducers/stopPointsList.js
(limited to 'app/javascript/journey_patterns')
diff --git a/app/javascript/journey_patterns/actions/index.js b/app/javascript/journey_patterns/actions/index.js
new file mode 100644
index 000000000..0c1cb5f5c
--- /dev/null
+++ b/app/javascript/journey_patterns/actions/index.js
@@ -0,0 +1,220 @@
+import Promise from 'promise-polyfill'
+
+// To add to window
+if (!window.Promise) {
+ window.Promise = Promise;
+}
+
+const actions = {
+ enterEditMode: () => ({
+ type: "ENTER_EDIT_MODE"
+ }),
+ exitEditMode: () => ({
+ type: "EXIT_EDIT_MODE"
+ }),
+ receiveJourneyPatterns : (json) => ({
+ type: "RECEIVE_JOURNEY_PATTERNS",
+ json
+ }),
+ receiveErrors : (json) => ({
+ type: "RECEIVE_ERRORS",
+ json
+ }),
+ unavailableServer : () => ({
+ type: 'UNAVAILABLE_SERVER'
+ }),
+ goToPreviousPage : (dispatch, pagination) => ({
+ type: 'GO_TO_PREVIOUS_PAGE',
+ dispatch,
+ pagination,
+ nextPage : false
+ }),
+ goToNextPage : (dispatch, pagination) => ({
+ type: 'GO_TO_NEXT_PAGE',
+ dispatch,
+ pagination,
+ nextPage : true
+ }),
+ updateCheckboxValue : (e, index) => ({
+ type : 'UPDATE_CHECKBOX_VALUE',
+ id : e.currentTarget.id,
+ index
+ }),
+ checkConfirmModal : (event, callback, stateChanged,dispatch) => {
+ if(stateChanged === true){
+ return actions.openConfirmModal(callback)
+ }else{
+ dispatch(actions.fetchingApi())
+ return callback
+ }
+ },
+ openConfirmModal : (callback) => ({
+ type : 'OPEN_CONFIRM_MODAL',
+ callback
+ }),
+ openEditModal : (index, journeyPattern) => ({
+ type : 'EDIT_JOURNEYPATTERN_MODAL',
+ index,
+ journeyPattern
+ }),
+ openCreateModal : () => ({
+ type : 'CREATE_JOURNEYPATTERN_MODAL'
+ }),
+ deleteJourneyPattern : (index) => ({
+ type : 'DELETE_JOURNEYPATTERN',
+ index,
+ }),
+ closeModal : () => ({
+ type : 'CLOSE_MODAL'
+ }),
+ saveModal : (index, data) => ({
+ type: 'SAVE_MODAL',
+ data,
+ index
+ }),
+ addJourneyPattern : (data) => ({
+ type: 'ADD_JOURNEYPATTERN',
+ data,
+ }),
+ savePage : (dispatch, currentPage) => ({
+ type: 'SAVE_PAGE',
+ dispatch
+ }),
+ updateTotalCount: (diff) => ({
+ type: 'UPDATE_TOTAL_COUNT',
+ diff
+ }),
+ fetchingApi: () =>({
+ type: 'FETCH_API'
+ }),
+ resetValidation: (target) => {
+ $(target).parent().removeClass('has-error').children('.help-block').remove()
+ },
+ humanOID : (oid) => oid.split(':')[2].split("-").pop(),
+ validateFields : (fields) => {
+ const test = []
+
+ Object.keys(fields).map(function(key) {
+ test.push(fields[key].validity.valid)
+ })
+ if(test.indexOf(false) >= 0) {
+ // Form is invalid
+ test.map(function(item, i) {
+ if(item == false) {
+ const k = Object.keys(fields)[i]
+ $(fields[k]).parent().addClass('has-error').children('.help-block').remove()
+ $(fields[k]).parent().append("" + fields[k].validationMessage + " ")
+ }
+ })
+ return false
+ } else {
+ // Form is valid
+ return true
+ }
+ },
+ submitJourneyPattern : (dispatch, state, next) => {
+ dispatch(actions.fetchingApi())
+ let urlJSON = window.location.pathname + ".json"
+ let hasError = false
+ fetch(urlJSON, {
+ credentials: 'same-origin',
+ method: 'PATCH',
+ contentType: 'application/json; charset=utf-8',
+ Accept: 'application/json',
+ body: JSON.stringify(state),
+ headers: {
+ 'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
+ }
+ }).then(response => {
+ if(!response.ok) {
+ hasError = true
+ }
+ return response.json()
+ }).then((json) => {
+ if(hasError == true) {
+ dispatch(actions.receiveErrors(json))
+ } else {
+ if(next) {
+ dispatch(next)
+ } else {
+ if(json.length != window.currentItemsLength){
+ dispatch(actions.updateTotalCount(window.currentItemsLength - json.length))
+ }
+ window.currentItemsLength = json.length
+ dispatch(actions.exitEditMode())
+ dispatch(actions.receiveJourneyPatterns(json))
+ }
+ }
+ })
+ },
+ fetchJourneyPatterns : (dispatch, currentPage, nextPage) => {
+ if(currentPage == undefined){
+ currentPage = 1
+ }
+ let journeyPatterns = []
+ let page
+
+ switch (nextPage) {
+ case true:
+ page = currentPage + 1
+ break
+ case false:
+ if(currentPage > 1){
+ page = currentPage - 1
+ }
+ break
+ default:
+ page = currentPage
+ break
+ }
+ let str = ".json"
+ if(page > 1){
+ str = '.json?page=' + page.toString()
+ }
+ let urlJSON = window.location.pathname + str
+ let hasError = false
+ fetch(urlJSON, {
+ credentials: 'same-origin',
+ }).then(response => {
+ if(response.status == 500) {
+ hasError = true
+ }
+ return response.json()
+ }).then((json) => {
+ if(hasError == true) {
+ dispatch(actions.unavailableServer())
+ } else {
+ if(json.length != 0){
+ let val
+ for (val of json){
+ for (let stop_point of val.route_short_description.stop_points){
+ stop_point.checked = false
+ val.stop_area_short_descriptions.map((element) => {
+ if(element.stop_area_short_description.id === stop_point.id){
+ stop_point.checked = true
+ }
+ })
+ }
+ journeyPatterns.push({
+ name: val.name,
+ object_id: val.object_id,
+ published_name: val.published_name,
+ registration_number: val.registration_number,
+ stop_points: val.route_short_description.stop_points,
+ deletable: false
+ })
+ }
+ }
+ window.currentItemsLength = journeyPatterns.length
+ dispatch(actions.receiveJourneyPatterns(journeyPatterns))
+ }
+ })
+ },
+ getChecked : (jp) => {
+ return jp.filter((obj) => {
+ return obj.checked
+ })
+ }
+}
+
+export default actions
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/components/App.js b/app/javascript/journey_patterns/components/App.js
new file mode 100644
index 000000000..ac6214cc1
--- /dev/null
+++ b/app/javascript/journey_patterns/components/App.js
@@ -0,0 +1,21 @@
+import React from 'react'
+import AddJourneyPattern from '../containers/AddJourneyPattern'
+import Navigate from '../containers/Navigate'
+import Modal from '../containers/Modal'
+import ConfirmModal from '../containers/ConfirmModal'
+import SaveJourneyPattern from '../containers/SaveJourneyPattern'
+import JourneyPatternList from '../containers/JourneyPatternList'
+
+const App = () => (
+
+)
+
+export default App
diff --git a/app/javascript/journey_patterns/components/ConfirmModal.js b/app/javascript/journey_patterns/components/ConfirmModal.js
new file mode 100644
index 000000000..2cc1bef44
--- /dev/null
+++ b/app/javascript/journey_patterns/components/ConfirmModal.js
@@ -0,0 +1,46 @@
+import React, { PropTypes } from 'react'
+
+export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCancel, journeyPatterns}) {
+ return (
+
+
+
+
+
+
Confirmation
+
+
+
+
Vous vous apprêtez à changer de page. Voulez-vous valider vos modifications avant cela ?
+
+
+
+ { onModalCancel(modal.confirmModal.callback) }}
+ >
+ Ne pas valider
+
+ { onModalAccept(modal.confirmModal.callback, journeyPatterns) }}
+ >
+ Valider
+
+
+
+
+
+
+ )
+}
+
+ConfirmModal.propTypes = {
+ modal: PropTypes.object.isRequired,
+ onModalAccept: PropTypes.func.isRequired,
+ onModalCancel: PropTypes.func.isRequired
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/components/CreateModal.js b/app/javascript/journey_patterns/components/CreateModal.js
new file mode 100644
index 000000000..d0eff6e57
--- /dev/null
+++ b/app/javascript/journey_patterns/components/CreateModal.js
@@ -0,0 +1,122 @@
+import React, { PropTypes, Component } from 'react'
+import actions from '../actions'
+
+export default class CreateModal extends Component {
+ constructor(props) {
+ super(props)
+ }
+
+ handleSubmit() {
+ if(actions.validateFields(this.refs) == true) {
+ this.props.onAddJourneyPattern(this.refs)
+ this.props.onModalClose()
+ $('#NewJourneyPatternModal').modal('hide')
+ }
+ }
+
+ render() {
+ if(this.props.status.isFetching == true || this.props.status.policy['journey_patterns.create'] == false || this.props.editMode == false) {
+ return false
+ }
+ if(this.props.status.fetchSuccess == true) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
Ajouter une mission
+
+
+ {(this.props.modal.type == 'create') && (
+
+ )}
+
+
+
+
+
+
+
+ )
+ } else {
+ return false
+ }
+ }
+}
+
+CreateModal.propTypes = {
+ index: PropTypes.number,
+ modal: PropTypes.object.isRequired,
+ status: PropTypes.object.isRequired,
+ onOpenCreateModal: PropTypes.func.isRequired,
+ onModalClose: PropTypes.func.isRequired,
+ onAddJourneyPattern: PropTypes.func.isRequired
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/components/EditModal.js b/app/javascript/journey_patterns/components/EditModal.js
new file mode 100644
index 000000000..699f89b85
--- /dev/null
+++ b/app/javascript/journey_patterns/components/EditModal.js
@@ -0,0 +1,110 @@
+import React, { PropTypes, Component } from 'react'
+import actions from '../actions'
+
+export default class EditModal extends Component {
+ constructor(props) {
+ super(props)
+ }
+
+ handleSubmit() {
+ if(actions.validateFields(this.refs) == true) {
+ this.props.saveModal(this.props.modal.modalProps.index, this.refs)
+ $('#JourneyPatternModal').modal('hide')
+ }
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ Editer la mission
+ {(this.props.modal.type == 'edit') && (
+ "{this.props.modal.modalProps.journeyPattern.name}"
+ )}
+
+
+
+ {(this.props.modal.type == 'edit') && (
+
+ )}
+
+
+
+
+ )
+ }
+}
+
+EditModal.propTypes = {
+ index: PropTypes.number,
+ modal: PropTypes.object,
+ onModalClose: PropTypes.func.isRequired,
+ saveModal: PropTypes.func.isRequired
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/components/JourneyPattern.js b/app/javascript/journey_patterns/components/JourneyPattern.js
new file mode 100644
index 000000000..dde73a957
--- /dev/null
+++ b/app/javascript/journey_patterns/components/JourneyPattern.js
@@ -0,0 +1,131 @@
+import React, { PropTypes, Component } from 'react'
+import actions from '../actions'
+
+export default class JourneyPattern extends Component{
+ constructor(props){
+ super(props)
+ this.previousCity = undefined
+ }
+
+ vehicleJourneyURL(jpOid) {
+ let routeURL = window.location.pathname.split('/', 7).join('/')
+ let vjURL = routeURL + '/vehicle_journeys?jp=' + jpOid
+
+ return (
+ Horaires des courses
+ )
+ }
+
+ cityNameChecker(sp) {
+ let bool = false
+ if(sp.city_name != this.previousCity){
+ bool = true
+ this.previousCity = sp.city_name
+ }
+ return (
+
+
+ this.props.onCheckboxChange(e)}
+ type='checkbox'
+ id={sp.id}
+ checked={sp.checked}
+ disabled={(this.props.value.deletable || this.props.status.policy['journey_patterns.update'] == false || this.props.editMode == false) ? 'disabled' : ''}
+ >
+
+
+
+
+ )
+ }
+
+ getErrors(errors) {
+ let err = Object.keys(errors).map((key, index) => {
+ return (
+
+ {key} { errors[key] }
+
+ )
+ })
+
+ return (
+
+ )
+ }
+
+ isDisabled(action) {
+ return !this.props.status.policy[`journey_patterns.${action}`] && !this.props.editMode
+ }
+
+ render() {
+ this.previousCity = undefined
+
+ return (
+
+ {/* Errors */}
+ {/* this.props.value.errors ? this.getErrors(this.props.value.errors) : '' */}
+
+
+
{this.props.value.object_id ? actions.humanOID(this.props.value.object_id) : '-'}
+
{this.props.value.registration_number}
+
{actions.getChecked(this.props.value.stop_points).length} arrêt(s)
+
+
+
+
+
+
+
+
+ Editer
+
+
+
+ {this.vehicleJourneyURL(this.props.value.object_id)}
+
+
+ {
+ e.preventDefault()
+ this.props.onDeleteJourneyPattern(this.props.index)}
+ }
+ >
+ Supprimer
+
+
+
+
+
+
+ {this.props.value.stop_points.map((stopPoint, i) =>{
+ return (
+
+ {this.cityNameChecker(stopPoint)}
+
+ )
+ })}
+
+ )
+ }
+}
+
+JourneyPattern.propTypes = {
+ value: PropTypes.object,
+ index: PropTypes.number,
+ onCheckboxChange: PropTypes.func.isRequired,
+ onOpenEditModal: PropTypes.func.isRequired,
+ onDeleteJourneyPattern: PropTypes.func.isRequired
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/components/JourneyPatterns.js b/app/javascript/journey_patterns/components/JourneyPatterns.js
new file mode 100644
index 000000000..4b2badabb
--- /dev/null
+++ b/app/javascript/journey_patterns/components/JourneyPatterns.js
@@ -0,0 +1,155 @@
+import React, { PropTypes, Component } from 'react'
+import _ from 'lodash'
+import JourneyPattern from './JourneyPattern'
+
+
+export default class JourneyPatterns extends Component {
+ constructor(props){
+ super(props)
+ this.previousCity = undefined
+ }
+ componentDidMount() {
+ this.props.onLoadFirstPage()
+ }
+ componentDidUpdate(prevProps, prevState) {
+ if(this.props.status.isFetching == false){
+ $('.table-2entries').each(function() {
+ var refH = []
+ var refCol = []
+
+ $(this).find('.t2e-head').children('div').each(function() {
+ var h = $(this).outerHeight();
+ refH.push(h)
+ });
+
+ var i = 0
+ $(this).find('.t2e-item').children('div').each(function() {
+ var h = $(this).outerHeight();
+ if(refCol.length < refH.length){
+ refCol.push(h)
+ } else {
+ if(h > refCol[i]) {
+ refCol[i] = h
+ }
+ }
+ if(i == (refH.length - 1)){
+ i = 0
+ } else {
+ i++
+ }
+ });
+
+ for(var n = 0; n < refH.length; n++) {
+ if(refCol[n] < refH[n]) {
+ refCol[n] = refH[n]
+ }
+ }
+
+ $(this).find('.th').css('height', refCol[0]);
+
+ for(var nth = 1; nth < refH.length; nth++) {
+ $(this).find('.td:nth-child('+ (nth + 1) +')').css('height', refCol[nth]);
+ }
+ });
+ }
+ }
+
+ cityNameChecker(sp) {
+ let bool = false
+ if(sp.city_name != this.previousCity){
+ bool = true
+ this.previousCity = sp.city_name
+ }
+ return (
+
+ {sp.name}
+
+ )
+ }
+
+ render() {
+ this.previousCity = undefined
+
+ if(this.props.status.isFetching == true) {
+ return (
+
+ )
+ } else {
+ return (
+
+
+ {(this.props.status.fetchSuccess == false) && (
+
+ Erreur :
+ la récupération des missions a rencontré un problème. Rechargez la page pour tenter de corriger le problème
+
+ )}
+
+ { _.some(this.props.journeyPatterns, 'errors') && (
+
+
Erreur :
+ {this.props.journeyPatterns.map((jp, index) =>
+ jp.errors && jp.errors.map((err, i) => {
+ return (
+
+ )
+ })
+ )}
+
+ )}
+
+
0) ? '' : ' no_result')}>
+
+
+
ID Mission
+
Code mission
+
Nb arrêts
+
+ {this.props.stopPointsList.map((sp, i) =>{
+ return (
+
+ {this.cityNameChecker(sp)}
+
+ )
+ })}
+
+
+
+
+ {this.props.journeyPatterns.map((journeyPattern, index) =>
+ this.props.onCheckboxChange(e, index)}
+ onOpenEditModal= {() => this.props.onOpenEditModal(index, journeyPattern)}
+ onDeleteJourneyPattern={() => this.props.onDeleteJourneyPattern(index)}
+ status= {this.props.status}
+ editMode= {this.props.editMode}
+ />
+ )}
+
+
+
+
+
+ )
+ }
+ }
+}
+
+JourneyPatterns.propTypes = {
+ journeyPatterns: PropTypes.array.isRequired,
+ stopPointsList: PropTypes.array.isRequired,
+ status: PropTypes.object.isRequired,
+ onCheckboxChange: PropTypes.func.isRequired,
+ onLoadFirstPage: PropTypes.func.isRequired,
+ onOpenEditModal: PropTypes.func.isRequired
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/components/Navigate.js b/app/javascript/journey_patterns/components/Navigate.js
new file mode 100644
index 000000000..f2fdd668f
--- /dev/null
+++ b/app/javascript/journey_patterns/components/Navigate.js
@@ -0,0 +1,62 @@
+import React, { PropTypes, Component } from 'react'
+import actions from '../actions'
+
+export default function Navigate({ dispatch, journeyPatterns, pagination, status }) {
+ let firstPage = 1
+ let lastPage = Math.ceil(pagination.totalCount / window.journeyPatternsPerPage)
+
+ let firstItemOnPage = firstPage + (pagination.perPage * (pagination.page - firstPage))
+ let lastItemOnPage = firstItemOnPage + (pagination.perPage - firstPage)
+
+ if(status.isFetching == true) {
+ return false
+ }
+ if(status.fetchSuccess == true) {
+ return (
+
+
+
+ Liste des missions {firstItemOnPage} à {(lastItemOnPage < pagination.totalCount) ? lastItemOnPage : pagination.totalCount} sur {pagination.totalCount}
+
+
+
+
+ )
+ } else {
+ return false
+ }
+}
+
+Navigate.propTypes = {
+ journeyPatterns: PropTypes.array.isRequired,
+ status: PropTypes.object.isRequired,
+ pagination: PropTypes.object.isRequired,
+ dispatch: PropTypes.func.isRequired
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/components/SaveJourneyPattern.js b/app/javascript/journey_patterns/components/SaveJourneyPattern.js
new file mode 100644
index 000000000..d071fa542
--- /dev/null
+++ b/app/javascript/journey_patterns/components/SaveJourneyPattern.js
@@ -0,0 +1,39 @@
+import React, { PropTypes, Component } from 'react'
+import actions from '../actions'
+
+export default class SaveJourneyPattern extends Component {
+ constructor(props){
+ super(props)
+ }
+
+ render() {
+ if(this.props.status.policy['journey_patterns.update'] == false) {
+ return false
+ }else{
+ return (
+
+ )
+ }
+ }
+}
+
+SaveJourneyPattern.propTypes = {
+ journeyPatterns: PropTypes.array.isRequired,
+ status: PropTypes.object.isRequired,
+ page: PropTypes.number.isRequired
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/containers/AddJourneyPattern.js b/app/javascript/journey_patterns/containers/AddJourneyPattern.js
new file mode 100644
index 000000000..b093fd111
--- /dev/null
+++ b/app/javascript/journey_patterns/containers/AddJourneyPattern.js
@@ -0,0 +1,30 @@
+import { connect } from 'react-redux'
+import actions from '../actions'
+import CreateModal from '../components/CreateModal'
+
+const mapStateToProps = (state) => {
+ return {
+ modal: state.modal,
+ journeyPatterns: state.journeyPatterns,
+ editMode: state.editMode,
+ status: state.status
+ }
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onModalClose: () =>{
+ dispatch(actions.closeModal())
+ },
+ onAddJourneyPattern: (data) =>{
+ dispatch(actions.addJourneyPattern(data))
+ },
+ onOpenCreateModal: () =>{
+ dispatch(actions.openCreateModal())
+ }
+ }
+}
+
+const AddJourneyPattern = connect(mapStateToProps, mapDispatchToProps)(CreateModal)
+
+export default AddJourneyPattern
diff --git a/app/javascript/journey_patterns/containers/ConfirmModal.js b/app/javascript/journey_patterns/containers/ConfirmModal.js
new file mode 100644
index 000000000..92ce09f33
--- /dev/null
+++ b/app/javascript/journey_patterns/containers/ConfirmModal.js
@@ -0,0 +1,30 @@
+import { connect } from 'react-redux'
+import actions from '../actions'
+import ConfirmModal from '../components/ConfirmModal'
+
+const mapStateToProps = (state) => {
+ return {
+ modal: state.modal,
+ journeyPatterns: state.journeyPatterns
+ }
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onModalAccept: (next, state) =>{
+ dispatch(actions.fetchingApi())
+ actions.submitJourneyPattern(dispatch, state, next)
+ },
+ onModalCancel: (next) =>{
+ dispatch(actions.fetchingApi())
+ dispatch(next)
+ },
+ onModalClose: () =>{
+ dispatch(actions.closeModal())
+ }
+ }
+}
+
+const ConfirmModalContainer = connect(mapStateToProps, mapDispatchToProps)(ConfirmModal)
+
+export default ConfirmModalContainer
diff --git a/app/javascript/journey_patterns/containers/JourneyPatternList.js b/app/javascript/journey_patterns/containers/JourneyPatternList.js
new file mode 100644
index 000000000..d98734407
--- /dev/null
+++ b/app/javascript/journey_patterns/containers/JourneyPatternList.js
@@ -0,0 +1,34 @@
+import { connect } from 'react-redux'
+import actions from '../actions'
+import JourneyPatterns from '../components/JourneyPatterns'
+
+const mapStateToProps = (state) => {
+ return {
+ journeyPatterns: state.journeyPatterns,
+ status: state.status,
+ editMode: state.editMode,
+ stopPointsList: state.stopPointsList
+ }
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onLoadFirstPage: () =>{
+ dispatch(actions.fetchingApi())
+ actions.fetchJourneyPatterns(dispatch)
+ },
+ onCheckboxChange: (e, index) =>{
+ dispatch(actions.updateCheckboxValue(e, index))
+ },
+ onOpenEditModal: (index, journeyPattern) =>{
+ dispatch(actions.openEditModal(index, journeyPattern))
+ },
+ onDeleteJourneyPattern: (index) =>{
+ dispatch(actions.deleteJourneyPattern(index))
+ }
+ }
+}
+
+const JourneyPatternList = connect(mapStateToProps, mapDispatchToProps)(JourneyPatterns)
+
+export default JourneyPatternList
diff --git a/app/javascript/journey_patterns/containers/Modal.js b/app/javascript/journey_patterns/containers/Modal.js
new file mode 100644
index 000000000..ace71a857
--- /dev/null
+++ b/app/javascript/journey_patterns/containers/Modal.js
@@ -0,0 +1,26 @@
+import { connect } from 'react-redux'
+import actions from '../actions'
+import EditModal from '../components/EditModal'
+import CreateModal from '../components/CreateModal'
+
+const mapStateToProps = (state) => {
+ return {
+ modal: state.modal,
+ journeyPattern: state.journeyPattern
+ }
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onModalClose: () =>{
+ dispatch(actions.closeModal())
+ },
+ saveModal: (index, data) =>{
+ dispatch(actions.saveModal(index, data))
+ }
+ }
+}
+
+const ModalContainer = connect(mapStateToProps, mapDispatchToProps)(EditModal, CreateModal)
+
+export default ModalContainer
diff --git a/app/javascript/journey_patterns/containers/Navigate.js b/app/javascript/journey_patterns/containers/Navigate.js
new file mode 100644
index 000000000..d34e0b4c5
--- /dev/null
+++ b/app/javascript/journey_patterns/containers/Navigate.js
@@ -0,0 +1,15 @@
+import { connect } from 'react-redux'
+import actions from '../actions'
+import NavigateComponent from '../components/Navigate'
+
+const mapStateToProps = (state) => {
+ return {
+ journeyPatterns: state.journeyPatterns,
+ status: state.status,
+ pagination: state.pagination
+ }
+}
+
+const Navigate = connect(mapStateToProps)(NavigateComponent)
+
+export default Navigate
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/containers/SaveJourneyPattern.js b/app/javascript/journey_patterns/containers/SaveJourneyPattern.js
new file mode 100644
index 000000000..b630c121c
--- /dev/null
+++ b/app/javascript/journey_patterns/containers/SaveJourneyPattern.js
@@ -0,0 +1,27 @@
+import { connect } from 'react-redux'
+import actions from '../actions'
+import SaveJourneyPatternComponent from '../components/SaveJourneyPattern'
+
+const mapStateToProps = (state) => {
+ return {
+ journeyPatterns: state.journeyPatterns,
+ editMode: state.editMode,
+ page: state.pagination.page,
+ status: state.status
+ }
+}
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ onEnterEditMode: () => {
+ dispatch(actions.enterEditMode())
+ },
+ onSubmitJourneyPattern: (next, state) => {
+ actions.submitJourneyPattern(dispatch, state, next)
+ }
+ }
+}
+
+const SaveJourneyPattern = connect(mapStateToProps, mapDispatchToProps)(SaveJourneyPatternComponent)
+
+export default SaveJourneyPattern
diff --git a/app/javascript/journey_patterns/reducers/editMode.js b/app/javascript/journey_patterns/reducers/editMode.js
new file mode 100644
index 000000000..bff976804
--- /dev/null
+++ b/app/javascript/journey_patterns/reducers/editMode.js
@@ -0,0 +1,10 @@
+export default function editMode(state = {}, action ) {
+ switch (action.type) {
+ case "ENTER_EDIT_MODE":
+ return true
+ case "EXIT_EDIT_MODE":
+ return false
+ default:
+ return state
+ }
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/reducers/index.js b/app/javascript/journey_patterns/reducers/index.js
new file mode 100644
index 000000000..2ffaf86d4
--- /dev/null
+++ b/app/javascript/journey_patterns/reducers/index.js
@@ -0,0 +1,18 @@
+import { combineReducers } from 'redux'
+import editMode from './editMode'
+import status from './status'
+import journeyPatterns from './journeyPatterns'
+import pagination from './pagination'
+import modal from './modal'
+import stopPointsList from './stopPointsList'
+
+const journeyPatternsApp = combineReducers({
+ editMode,
+ status,
+ journeyPatterns,
+ pagination,
+ stopPointsList,
+ modal
+})
+
+export default journeyPatternsApp
diff --git a/app/javascript/journey_patterns/reducers/journeyPatterns.js b/app/javascript/journey_patterns/reducers/journeyPatterns.js
new file mode 100644
index 000000000..7702e21bc
--- /dev/null
+++ b/app/javascript/journey_patterns/reducers/journeyPatterns.js
@@ -0,0 +1,90 @@
+import _ from 'lodash'
+import actions from "../actions"
+
+export default function journeyPattern(state = {}, action) {
+ switch (action.type) {
+ case 'ADD_JOURNEYPATTERN':
+ let stopPoints = window.stopPoints
+
+ if(stopPoints != undefined) {
+ stopPoints.map((s)=>{
+ s.checked = false
+ return s
+ })
+ }
+ return {
+ name: action.data.name.value,
+ published_name: action.data.published_name.value,
+ registration_number: action.data.registration_number.value,
+ stop_points: stopPoints,
+ deletable: false
+ }
+ case 'UPDATE_CHECKBOX_VALUE':
+ var updatedStopPoints = state.stop_points.map((s) => {
+ if (String(s.id) == action.id) {
+ return _.assign({}, s, {checked : !s.checked})
+ }else {
+ return s
+ }
+ })
+ return _.assign({}, state, {stop_points: updatedStopPoints})
+ default:
+ return state
+ }
+}
+
+const journeyPatterns = (state = [], action) => {
+ switch (action.type) {
+ case 'RECEIVE_JOURNEY_PATTERNS':
+ return [...action.json]
+ case 'RECEIVE_ERRORS':
+ return [...action.json]
+ case 'GO_TO_PREVIOUS_PAGE':
+ $('#ConfirmModal').modal('hide')
+ if(action.pagination.page > 1){
+ actions.fetchJourneyPatterns(action.dispatch, action.pagination.page, action.nextPage)
+ }
+ return state
+ case 'GO_TO_NEXT_PAGE':
+ $('#ConfirmModal').modal('hide')
+ if (action.pagination.totalCount - (action.pagination.page * action.pagination.perPage) > 0){
+ actions.fetchJourneyPatterns(action.dispatch, action.pagination.page, action.nextPage)
+ }
+ return state
+ case 'UPDATE_CHECKBOX_VALUE':
+ return state.map((j, i) =>{
+ if(i == action.index) {
+ return journeyPattern(j, action)
+ } else {
+ return j
+ }
+ })
+ case 'DELETE_JOURNEYPATTERN':
+ return state.map((j, i) =>{
+ if(i == action.index) {
+ return _.assign({}, j, {deletable: true})
+ } else {
+ return j
+ }
+ })
+ case 'ADD_JOURNEYPATTERN':
+ return [
+ journeyPattern(state, action),
+ ...state
+ ]
+ case 'SAVE_MODAL':
+ return state.map((j, i) =>{
+ if(i == action.index) {
+ return _.assign({}, j, {
+ name: action.data.name.value,
+ published_name: action.data.published_name.value,
+ registration_number: action.data.registration_number.value
+ })
+ } else {
+ return j
+ }
+ })
+ default:
+ return state
+ }
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/reducers/modal.js b/app/javascript/journey_patterns/reducers/modal.js
new file mode 100644
index 000000000..0a96f1679
--- /dev/null
+++ b/app/javascript/journey_patterns/reducers/modal.js
@@ -0,0 +1,41 @@
+import _ from 'lodash'
+
+export default function modal(state = {}, action) {
+ switch (action.type) {
+ case 'OPEN_CONFIRM_MODAL':
+ $('#ConfirmModal').modal('show')
+ return _.assign({}, state, {
+ type: 'confirm',
+ confirmModal: {
+ callback: action.callback,
+ }
+ })
+ case 'EDIT_JOURNEYPATTERN_MODAL':
+ return {
+ type: 'edit',
+ modalProps: {
+ index: action.index,
+ journeyPattern: action.journeyPattern
+ },
+ confirmModal: {}
+ }
+ case 'CREATE_JOURNEYPATTERN_MODAL':
+ return {
+ type: 'create',
+ modalProps: {},
+ confirmModal: {}
+ }
+ case 'DELETE_JOURNEYPATTERN':
+ return _.assign({}, state, { type: '' })
+ case 'SAVE_MODAL':
+ return _.assign({}, state, { type: '' })
+ case 'CLOSE_MODAL':
+ return {
+ type: '',
+ modalProps: {},
+ confirmModal: {}
+ }
+ default:
+ return state
+ }
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/reducers/pagination.js b/app/javascript/journey_patterns/reducers/pagination.js
new file mode 100644
index 000000000..01fdf21d4
--- /dev/null
+++ b/app/javascript/journey_patterns/reducers/pagination.js
@@ -0,0 +1,35 @@
+import _ from 'lodash'
+
+export default function pagination (state = {}, action) {
+ switch (action.type) {
+ case 'RECEIVE_JOURNEY_PATTERNS':
+ return _.assign({}, state, {stateChanged: false})
+ case 'GO_TO_PREVIOUS_PAGE':
+ if (action.pagination.page > 1){
+ toggleOnConfirmModal()
+ return _.assign({}, state, {page : action.pagination.page - 1, stateChanged: false})
+ }
+ return state
+ case 'GO_TO_NEXT_PAGE':
+ if (state.totalCount - (action.pagination.page * action.pagination.perPage) > 0){
+ toggleOnConfirmModal()
+ return _.assign({}, state, {page : action.pagination.page + 1, stateChanged: false})
+ }
+ return state
+ case 'UPDATE_CHECKBOX_VALUE':
+ case 'ADD_JOURNEYPATTERN':
+ case 'SAVE_MODAL':
+ toggleOnConfirmModal('modal')
+ return _.assign({}, state, {stateChanged: true})
+ case 'UPDATE_TOTAL_COUNT':
+ return _.assign({}, state, {totalCount : state.totalCount - action.diff })
+ default:
+ return state
+ }
+}
+
+const toggleOnConfirmModal = (arg = '') =>{
+ $('.confirm').each(function(){
+ $(this).data('toggle','')
+ })
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/reducers/status.js b/app/javascript/journey_patterns/reducers/status.js
new file mode 100644
index 000000000..88c75966d
--- /dev/null
+++ b/app/javascript/journey_patterns/reducers/status.js
@@ -0,0 +1,21 @@
+import _ from 'lodash'
+import actions from '../actions'
+
+export default function status (state = {}, action) {
+ switch (action.type) {
+ case 'UNAVAILABLE_SERVER':
+ return _.assign({}, state, {fetchSuccess: false})
+ case 'FETCH_API':
+ return _.assign({}, state, {isFetching: true})
+ case 'RECEIVE_JOURNEY_PATTERNS':
+ return _.assign({}, state, {fetchSuccess: true, isFetching: false})
+ case 'RECEIVE_ERRORS':
+ return _.assign({}, state, {isFetching: false})
+ case 'ENTER_EDIT_MODE':
+ return _.assign({}, state, {editMode: true})
+ case 'EXIT_EDIT_MODE':
+ return _.assign({}, state, {editMode: false})
+ default:
+ return state
+ }
+}
\ No newline at end of file
diff --git a/app/javascript/journey_patterns/reducers/stopPointsList.js b/app/javascript/journey_patterns/reducers/stopPointsList.js
new file mode 100644
index 000000000..ee5eb1a80
--- /dev/null
+++ b/app/javascript/journey_patterns/reducers/stopPointsList.js
@@ -0,0 +1,6 @@
+export default function stopPointsList (state = [], action) {
+ switch (action.type) {
+ default:
+ return state
+ }
+}
\ No newline at end of file
--
cgit v1.2.3