af83/chouette-core

View on GitHub
app/packs/src/time_tables/actions/index.js

Summary

Maintainability
C
1 day
Test Coverage
import assign from 'lodash/assign'
import range from 'lodash/range'
import reject from 'lodash/reject'
import some from 'lodash/some'
import every from 'lodash/every'

const actions = {
  weekDays: (index) => {
    return range(1, 8).map(n => I18n.t('time_tables.edit.metas.days')[n])
  },
  strToArrayDayTypes: (str) =>{
    return actions.weekDays().map(day => str.indexOf(day) !== -1)
  },
  arrayToStrDayTypes: (dayTypes) => {
    let newDayTypes = dayTypes.reduce((arr, dayActive, i) => {
      if (dayActive) arr.push(actions.weekDays()[i])
      return arr
    }, [])

    return newDayTypes.join(',')
  },
  fetchingApi: () =>({
    type: 'FETCH_API'
  }),
  receiveErrors : (json) => ({
    type: "RECEIVE_ERRORS",
    json
  }),
  unavailableServer: () => ({
    type: 'UNAVAILABLE_SERVER'
  }),
  receiveMonth: (json) => ({
    type: 'RECEIVE_MONTH',
    json
  }),
  receiveTimeTables: (json) => ({
    type: 'RECEIVE_TIME_TABLES',
    json
  }),
  goToPreviousPage : (dispatch, pagination) => ({
    type: 'GO_TO_PREVIOUS_PAGE',
    dispatch,
    pagination,
    nextPage : false
  }),
  goToNextPage : (dispatch, pagination) => ({
    type: 'GO_TO_NEXT_PAGE',
    dispatch,
    pagination,
    nextPage : true
  }),
  changePage : (dispatch, val) => ({
    type: 'CHANGE_PAGE',
    dispatch,
    page: val
  }),
  updateDayTypes: (dayTypes) => ({
    type: 'UPDATE_DAY_TYPES',
    dayTypes
  }),
  updateCurrentMonthFromDaytypes: (dayTypes) => ({
    type: 'UPDATE_CURRENT_MONTH_FROM_DAYTYPES',
    dayTypes
  }),
  updateComment: (comment) => ({
    type: 'UPDATE_COMMENT',
    comment
  }),
  updateShared: (shared) => ({
    type: 'UPDATE_SHARED',
    shared
  }),
  updateColor: (color) => ({
    type: 'UPDATE_COLOR',
    color
  }),
  deletePeriod: (index, dayTypes) => ({
    type: 'DELETE_PERIOD',
    index,
    dayTypes
  }),
  openAddPeriodForm: () => ({
    type: 'OPEN_ADD_PERIOD_FORM'
  }),
  openEditPeriodForm: (period, index) => ({
    type: 'OPEN_EDIT_PERIOD_FORM',
    period,
    index
  }),
  closePeriodForm: () => ({
    type: 'CLOSE_PERIOD_FORM'
  }),
  resetModalErrors: () => ({
    type: 'RESET_MODAL_ERRORS'
  }),
  updatePeriodForm: (val, group, selectType) => ({
    type: 'UPDATE_PERIOD_FORM',
    val,
    group,
    selectType
  }),
  validatePeriodForm: (modalProps, timeTablePeriods, metas, timetableInDates, error) => ({
    type: 'VALIDATE_PERIOD_FORM',
    modalProps,
    timeTablePeriods,
    metas,
    timetableInDates,
    error
  }),
  addIncludedDate: (index, dayTypes, date) => ({
    type: 'ADD_INCLUDED_DATE',
    index,
    dayTypes,
    date
  }),
  removeIncludedDate: (index, dayTypes, date) => ({
    type: 'REMOVE_INCLUDED_DATE',
    index,
    dayTypes,
    date
  }),
  addExcludedDate: (index, dayTypes, date) => ({
    type: 'ADD_EXCLUDED_DATE',
    index,
    dayTypes,
    date
  }),
  removeExcludedDate: (index, dayTypes, date) => ({
    type: 'REMOVE_EXCLUDED_DATE',
    index,
    dayTypes,
    date
  }),
  openConfirmModal : (callback) => ({
    type : 'OPEN_CONFIRM_MODAL',
    callback
  }),
  showErrorModal: (error) => ({
    type: 'OPEN_ERROR_MODAL',
    error
  }),
  closeModal : () => ({
    type : 'CLOSE_MODAL'
  }),
  monthName(strDate) {
    let monthList = range(1,13).map(n => I18n.t('calendars.months.'+ n ))
    let date = new Date(strDate)
    return monthList[date.getUTCMonth()]
  },
  getHumanDate(strDate, mLimit) {
    let origin = strDate.split('-')
    let D = origin[2]
    let M = actions.monthName(strDate).toLowerCase()
    let Y = origin[0]

    if(mLimit && M.length > mLimit) {
      M = M.substr(0, mLimit) + '.'
    }

    return (D + ' ' + M + ' ' + Y)
  },
  getLocaleDate(strDate) {
    let date = new Date(strDate)
    return date.toLocaleDateString(I18n.locale)
  },
  updateSynthesis: ({current_month, time_table_dates: dates, time_table_periods: periods}) => {
    let newPeriods = reject(periods, 'deleted')
    let improvedCM = current_month.map((d, i) => {
      let isInPeriod = actions.isInPeriod(newPeriods, d.date)
      let isIncluded = some(dates, {'date': d.date, 'in_out': true})
      return assign({}, current_month[i], {
        in_periods: isInPeriod,
        include_date: isIncluded,
        excluded_date: !isInPeriod ? false : current_month[i].excluded_date
      })
    })
    return improvedCM
  },
  isInPeriod: (periods, date) => {
    date = new Date(date)

    let i = 0;
    while(i < periods.length){
      let period = periods[i]
      let begin = new Date(period.period_start)
      let end = new Date(period.period_end)
      if (date >= begin && date <= end) return true
      i++
    }

    return false
  },
  checkConfirmModal: (event, callback, stateChanged, dispatch, metas, timetable) => {
    if(stateChanged){
      const error = actions.errorModalKey(timetable.time_table_periods, metas.day_types)
      if(error){
        return actions.showErrorModal(error)
      }else{
        return actions.openConfirmModal(callback)
      }
    }else{
      dispatch(actions.fetchingApi())
      return callback
    }
  },
  formatDate: (props) => {
    return props.year + '-' + props.month + '-' + props.day
  },
  checkErrorsInPeriods: (start, end, index, periods) => {
    let error = ''
    start = new Date(start)
    end = new Date(end)

    for (let i = 0; i < periods.length; i++) {
      let period = periods[i]
      if (index !== i && !period.deleted) {
        if (new Date(period.period_start) <= end && new Date(period.period_end) >= start)  {
          error = I18n.t('time_tables.edit.error_submit.periods_overlaps')
          break
        }
      }
    }
    return error
  },
  checkErrorsInDates: (start, end, in_days) => {
    let error = ''
    start = new Date(start)
    end = new Date(end)
    let i = 0;
    while(i < in_days){
      let day = in_days[i]
      if (start <= new Date(day.date) && end >= new Date(day.date)) {
        error = I18n.t('time_tables.edit.error_submit.dates_overlaps')
        break
      }
      i ++
    }
    return error
  },
  fetchTimeTables: (dispatch, nextPage) => {
    let urlJSON = window.timetablesUrl || window.location.pathname.split('/', 5).join('/')

    if(nextPage) {
      urlJSON += "/month.json?date=" + nextPage
    }else{
      urlJSON += ".json"
    }
    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(nextPage){
          dispatch(actions.receiveMonth(json))
        }else{
          dispatch(actions.receiveTimeTables(json))
        }
      }
    })
  },
  submitTimetable: (dispatch, timetable, metas, next) => {
    dispatch(actions.fetchingApi())
    let strDayTypes = actions.arrayToStrDayTypes(metas.day_types)
    metas.day_types = strDayTypes
    let sentState = assign({}, timetable, metas)
    let urlJSON = window.timetablesUrl
    let hasError = false
    fetch(urlJSON + '.json', {
      credentials: 'same-origin',
      method: 'PATCH',
      contentType: 'application/json; charset=utf-8',
      Accept: 'application/json',
      body: JSON.stringify(sentState),
      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 {
          dispatch(actions.receiveTimeTables(json))
          window.location.assign(window.redirectUrl)
        }
      }
    })
  },
  errorModalKey: (periods, dayTypes) => {
    // const withoutPeriodsWithDaysTypes = reject(periods, 'deleted').length == 0 && some(dayTypes) && "withoutPeriodsWithDaysTypes"
    const withPeriodsWithoutDayTypes = reject(periods, 'deleted').length > 0 &&  every(dayTypes, dt => dt == false) && "withPeriodsWithoutDayTypes"

    // return (withoutPeriodsWithDaysTypes || withPeriodsWithoutDayTypes) && (withoutPeriodsWithDaysTypes ? "withoutPeriodsWithDaysTypes" : "withPeriodsWithoutDayTypes")
    return withPeriodsWithoutDayTypes

  },
  errorModalMessage: (errorKey) => {
    switch (errorKey) {
      case "withoutPeriodsWithDaysTypes":
        return I18n.t('time_tables.edit.error_modal.withoutPeriodsWithDaysTypes')
      case "withPeriodsWithoutDayTypes":
        return I18n.t('time_tables.edit.error_modal.withPeriodsWithoutDayTypes')
      default:
        return errorKey

    }
  }
}

export default actions