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 --- .../time_tables/components/ConfirmModal.js | 50 +++++++ .../time_tables/components/ErrorModal.js | 42 ++++++ .../time_tables/components/ExceptionsInDay.js | 71 ++++++++++ app/javascript/time_tables/components/Metas.js | 139 +++++++++++++++++++ app/javascript/time_tables/components/Navigate.js | 88 ++++++++++++ .../time_tables/components/PeriodForm.js | 148 +++++++++++++++++++++ .../time_tables/components/PeriodManager.js | 85 ++++++++++++ .../time_tables/components/PeriodsInDay.js | 75 +++++++++++ .../time_tables/components/SaveTimetable.js | 42 ++++++ .../time_tables/components/TagsSelect2.js | 77 +++++++++++ .../time_tables/components/TimeTableDay.js | 31 +++++ app/javascript/time_tables/components/Timetable.js | 115 ++++++++++++++++ 12 files changed, 963 insertions(+) create mode 100644 app/javascript/time_tables/components/ConfirmModal.js create mode 100644 app/javascript/time_tables/components/ErrorModal.js create mode 100644 app/javascript/time_tables/components/ExceptionsInDay.js create mode 100644 app/javascript/time_tables/components/Metas.js create mode 100644 app/javascript/time_tables/components/Navigate.js create mode 100644 app/javascript/time_tables/components/PeriodForm.js create mode 100644 app/javascript/time_tables/components/PeriodManager.js create mode 100644 app/javascript/time_tables/components/PeriodsInDay.js create mode 100644 app/javascript/time_tables/components/SaveTimetable.js create mode 100644 app/javascript/time_tables/components/TagsSelect2.js create mode 100644 app/javascript/time_tables/components/TimeTableDay.js create mode 100644 app/javascript/time_tables/components/Timetable.js (limited to 'app/javascript/time_tables/components') diff --git a/app/javascript/time_tables/components/ConfirmModal.js b/app/javascript/time_tables/components/ConfirmModal.js new file mode 100644 index 000000000..d89170ee7 --- /dev/null +++ b/app/javascript/time_tables/components/ConfirmModal.js @@ -0,0 +1,50 @@ +import React, { PropTypes } from 'react' + +export default function ConfirmModal({dispatch, modal, onModalAccept, onModalCancel, timetable, metas}, {I18n}) { + return ( +
+
+
+
+
+

{I18n.time_tables.edit.confirm_modal.title}

+
+
+
+

{I18n.time_tables.edit.confirm_modal.message}

+
+
+
+ + +
+
+
+
+
+ ) +} + +ConfirmModal.propTypes = { + modal: PropTypes.object.isRequired, + onModalAccept: PropTypes.func.isRequired, + onModalCancel: PropTypes.func.isRequired +} + +ConfirmModal.contextTypes = { + I18n: PropTypes.object +} \ No newline at end of file diff --git a/app/javascript/time_tables/components/ErrorModal.js b/app/javascript/time_tables/components/ErrorModal.js new file mode 100644 index 000000000..e810f49ab --- /dev/null +++ b/app/javascript/time_tables/components/ErrorModal.js @@ -0,0 +1,42 @@ +import React, { PropTypes } from 'react' +import actions from '../actions' + +export default function ErrorModal({dispatch, modal, onModalClose}, {I18n}) { + return ( +
+
+
+
+
+

{I18n.time_tables.edit.error_modal.title}

+
+
+
+

{actions.errorModalMessage(modal.modalProps.error)}

+
+
+
+ +
+
+
+
+
+ ) +} + +ErrorModal.propTypes = { + modal: PropTypes.object.isRequired, + onModalClose: PropTypes.func.isRequired +} + +ErrorModal.contextTypes = { + I18n: PropTypes.object +} \ No newline at end of file diff --git a/app/javascript/time_tables/components/ExceptionsInDay.js b/app/javascript/time_tables/components/ExceptionsInDay.js new file mode 100644 index 000000000..3335ee89d --- /dev/null +++ b/app/javascript/time_tables/components/ExceptionsInDay.js @@ -0,0 +1,71 @@ +import React, { PropTypes, Component } from 'react' +import actions from '../actions' + +export default class ExceptionsInDay extends Component { + constructor(props) { + super(props) + } + + handleClick() { + const {index, day, metas: {day_types} } = this.props + if (day.in_periods && day_types[day.wday]) { + day.excluded_date ? this.props.onRemoveExcludedDate(index, day_types, day.date) : this.props.onAddExcludedDate(index, day_types, day.date) + } else { + day.include_date ? this.props.onRemoveIncludedDate(index, day_types, day.date) : this.props.onAddIncludedDate(index, day_types, day.date) + } + } + + render() { + {/* display add or remove link, only if true in daytypes */} + {/* display add or remove link, according to context (presence in period, or not) */} + if(this.props.value.current_month[this.props.index].in_periods == true && this.props.blueDaytype == true) { + return ( +
+ +
+ ) + } else { + return ( +
+ +
+ ) + // } else if(this.props.value.current_month[this.props.index].in_periods == true && this.props.blueDaytype == false){ + // return ( + //
+ // ) + // } else{ + // return false + // } + } + } +} + +ExceptionsInDay.propTypes = { + value: PropTypes.object.isRequired, + metas: PropTypes.object.isRequired, + blueDaytype: PropTypes.bool.isRequired, + onExcludeDateFromPeriod: PropTypes.func.isRequired, + onIncludeDateInPeriod: PropTypes.func.isRequired, + index: PropTypes.number.isRequired +} diff --git a/app/javascript/time_tables/components/Metas.js b/app/javascript/time_tables/components/Metas.js new file mode 100644 index 000000000..7098d2b82 --- /dev/null +++ b/app/javascript/time_tables/components/Metas.js @@ -0,0 +1,139 @@ +import React, { PropTypes } from 'react' +import actions from '../actions' +import TagsSelect2 from './TagsSelect2' + +export default function Metas({metas, onUpdateDayTypes, onUpdateComment, onUpdateColor, onSelect2Tags, onUnselect2Tags}, {I18n}) { + let colorList = ["", "#9B9B9B", "#FFA070", "#C67300", "#7F551B", "#41CCE3", "#09B09C", "#3655D7", "#6321A0", "#E796C6", "#DD2DAA"] + return ( +
+
+
+ {/* comment (name) */} +
+ +
+ (onUpdateComment(e.currentTarget.value))} + /> +
+
+ + {/* color */} +
+ +
+
+ + +
+ {colorList.map((c, i) => + {onUpdateColor(c)}} + > + + + )} +
+
+
+
+ + {/* tags */} +
+ +
+ onSelect2Tags(e)} + onUnselect2Tags={(e) => onUnselect2Tags(e)} + /> +
+
+ + {/* calendar */} +
+ +
+ {metas.calendar ? metas.calendar.name : I18n.time_tables.edit.metas.no_calendar} +
+
+ + {/* day_types */} +
+ +
+
+ {metas.day_types.map((day, i) => +
+
+ +
+
+ )} +
+
+
+
+
+
+ ) +} + +Metas.propTypes = { + metas: PropTypes.object.isRequired, + onUpdateDayTypes: PropTypes.func.isRequired, + onUpdateColor: PropTypes.func.isRequired, + onUpdateColor: PropTypes.func.isRequired, + onSelect2Tags: PropTypes.func.isRequired, + onUnselect2Tags: PropTypes.func.isRequired +} + +Metas.contextTypes = { + I18n: PropTypes.object +} diff --git a/app/javascript/time_tables/components/Navigate.js b/app/javascript/time_tables/components/Navigate.js new file mode 100644 index 000000000..6ae80bce0 --- /dev/null +++ b/app/javascript/time_tables/components/Navigate.js @@ -0,0 +1,88 @@ +import React, { PropTypes, Component } from 'react' +import _ from 'lodash' +import actions from '../actions' + +export default function Navigate({ dispatch, metas, timetable, pagination, status, filters}) { + if(status.isFetching == true) { + return false + } + if(status.fetchSuccess == true) { + let pageIndex = pagination.periode_range.indexOf(pagination.currentPage) + let firstPage = pageIndex == 0 + let lastPage = pageIndex == pagination.periode_range.length - 1 + return ( +
+
{e.preventDefault()}}> + {/* date selector */} +
+
+
+ {pagination.currentPage ? (actions.monthName(pagination.currentPage) + ' ' + new Date(pagination.currentPage).getFullYear()) : ''} + +
+
    + {_.map(pagination.periode_range, (month, i) => ( +
  • + +
  • + ))} +
+
+
+ + {/* prev/next */} +
+
+ + +
+
+
+
+ ) + } else { + return false + } +} + +Navigate.propTypes = { + status: PropTypes.object.isRequired, + pagination: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired +} \ No newline at end of file diff --git a/app/javascript/time_tables/components/PeriodForm.js b/app/javascript/time_tables/components/PeriodForm.js new file mode 100644 index 000000000..893a1fa6a --- /dev/null +++ b/app/javascript/time_tables/components/PeriodForm.js @@ -0,0 +1,148 @@ +import React, { PropTypes } from 'react' +import _ from 'lodash' +let monthsArray = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'] + +const formatNumber = (val) => { + return ("0" + val).slice(-2) +} + +const makeDaysOptions = (daySelected) => { + let arr = [] + for(let i = 1; i < 32; i++) { + arr.push() + } + return arr +} + +const makeMonthsOptions = (monthSelected) => { + let arr = [] + for(let i = 1; i < 13; i++) { + arr.push() + } + return arr +} + +const makeYearsOptions = (yearSelected) => { + let arr = [] + let startYear = new Date().getFullYear() - 3 + for(let i = startYear; i <= startYear + 6; i++) { + arr.push() + } + return arr +} + +export default function PeriodForm({modal, timetable, metas, onOpenAddPeriodForm, onClosePeriodForm, onUpdatePeriodForm, onValidatePeriodForm}, {I18n}) { + return ( +
+
+
+
+ {modal.modalProps.active && +
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+ + + +
+
+
+
+
+ +
+ + {modal.modalProps.error} + + + +
+
+ } + {!modal.modalProps.active && +
+ +
+ } +
+
+
+
+ ) +} + +PeriodForm.propTypes = { + modal: PropTypes.object.isRequired, + metas: PropTypes.object.isRequired, + onOpenAddPeriodForm: PropTypes.func.isRequired, + onClosePeriodForm: PropTypes.func.isRequired, + onUpdatePeriodForm: PropTypes.func.isRequired, + onValidatePeriodForm: PropTypes.func.isRequired, + timetable: PropTypes.object.isRequired +} + +PeriodForm.contextTypes = { + I18n: PropTypes.object +} \ No newline at end of file diff --git a/app/javascript/time_tables/components/PeriodManager.js b/app/javascript/time_tables/components/PeriodManager.js new file mode 100644 index 000000000..9922ce2c4 --- /dev/null +++ b/app/javascript/time_tables/components/PeriodManager.js @@ -0,0 +1,85 @@ +import React, { PropTypes, Component } from 'react' +import actions from '../actions' + +export default class PeriodManager extends Component { + constructor(props, context) { + super(props, context) + } + + toEndPeriod(curr, end) { + let diff + + let startCurrM = curr.split('-')[1] + let endPeriodM = end.split('-')[1] + + let lastDayInM = new Date(curr.split('-')[2], startCurrM + 1, 0) + lastDayInM = lastDayInM.toJSON().substr(0, 10).split('-')[2] + + if(startCurrM === endPeriodM) { + diff = (end.split('-')[2] - curr.split('-')[2]) + } else { + diff = (lastDayInM - curr.split('-')[2]) + } + + return diff + } + + render() { + return ( +
+

+ {actions.getLocaleDate(this.props.value.period_start) + ' > ' + actions.getLocaleDate(this.props.value.period_end)} +

+ +
+
+ +
+ +
+
+ ) + } +} + +PeriodManager.propTypes = { + value: PropTypes.object.isRequired, + currentDate: PropTypes.object.isRequired, + onDeletePeriod: PropTypes.func.isRequired, + onOpenEditPeriodForm: PropTypes.func.isRequired +} + +PeriodManager.contextTypes = { + I18n: PropTypes.object +} \ No newline at end of file diff --git a/app/javascript/time_tables/components/PeriodsInDay.js b/app/javascript/time_tables/components/PeriodsInDay.js new file mode 100644 index 000000000..888537579 --- /dev/null +++ b/app/javascript/time_tables/components/PeriodsInDay.js @@ -0,0 +1,75 @@ +import React, { PropTypes, Component } from 'react' +import PeriodManager from './PeriodManager' + +export default class PeriodsInDay extends Component { + constructor(props) { + super(props) + } + + isIn(date) { + let currentDate = date.getTime() + let cls = 'td' + let periods = this.props.value + + periods.map((p, i) => { + if (!p.deleted){ + let begin = new Date(p.period_start).getTime() + let end = new Date(p.period_end).getTime() + + if(currentDate >= begin && currentDate <= end) { + if(currentDate == begin) { + cls += ' in_periods start_period' + } else if(currentDate == end) { + cls += ' in_periods end_period' + } else { + cls += ' in_periods' + } + } + } + }) + return cls + } + + render() { + return ( +
+ {this.props.value.map((p, i) => { + if(!p.deleted){ + let begin = new Date(p.period_start).getTime() + let end = new Date(p.period_end).getTime() + let d = this.props.currentDate.getTime() + + if(d >= begin && d <= end) { + if(d == begin || (this.props.currentDate.getUTCDate() == 1)) { + return ( + + ) + } else { + return false + } + } + }else{ + return false + } + })} +
+ ) + } +} + +PeriodsInDay.propTypes = { + value: PropTypes.array.isRequired, + currentDate: PropTypes.object.isRequired, + index: PropTypes.number.isRequired, + onDeletePeriod: PropTypes.func.isRequired +} diff --git a/app/javascript/time_tables/components/SaveTimetable.js b/app/javascript/time_tables/components/SaveTimetable.js new file mode 100644 index 000000000..0dffc7936 --- /dev/null +++ b/app/javascript/time_tables/components/SaveTimetable.js @@ -0,0 +1,42 @@ +import React, { PropTypes, Component } from 'react' +import _ from 'lodash' +import actions from '../actions' + +export default class SaveTimetable extends Component{ + constructor(props){ + super(props) + } + + render() { + const error = actions.errorModalKey(this.props.timetable.time_table_periods, this.props.metas.day_types) + + return ( +
+
+
{e.preventDefault()}}> + +
+
+
+ ) + } +} + +SaveTimetable.propTypes = { + timetable: PropTypes.object.isRequired, + status: PropTypes.object.isRequired, + metas: PropTypes.object.isRequired +} \ No newline at end of file diff --git a/app/javascript/time_tables/components/TagsSelect2.js b/app/javascript/time_tables/components/TagsSelect2.js new file mode 100644 index 000000000..24f473f42 --- /dev/null +++ b/app/javascript/time_tables/components/TagsSelect2.js @@ -0,0 +1,77 @@ +import React, { PropTypes, Component } from 'react' +import _ from 'lodash' +import Select2 from 'react-select2-wrapper' + +// get JSON full path +let origin = window.location.origin +let path = window.location.pathname.split('/', 4).join('/') + +export default class TagsSelect2 extends Component { + constructor(props, context) { + super(props, context) + } + + mapKeys(array){ + return array.map((item) => + _.mapKeys(item, (v, k) => + ((k == 'name') ? 'text' : k) + ) + ) + } + + render() { + return ( + this.props.onSelect2Tags(e)} + onUnselect={(e) => setTimeout( () => this.props.onUnselect2Tags(e, 150))} + multiple={true} + ref='tags_id' + options={{ + tags:true, + createTag: function(params) { + return {name: params.term, text: params.term, id: params.term} + }, + allowClear: true, + theme: 'bootstrap', + width: '100%', + placeholder: this.context.I18n.time_tables.edit.select2.tag.placeholder, + ajax: { + url: origin + path + '/tags.json', + dataType: 'json', + delay: '500', + data: function(params) { + return { + tag: params.term, + }; + }, + processResults: function(data, params) { + let items = _.filter(data, ({name}) => name.includes(params.term) ) + return { + results: items.map( + item => _.assign( + {}, + item, + {text: item.name} + ) + ) + }; + }, + cache: true + }, + minimumInputLength: 1, + templateResult: formatRepo + }} + /> + ) + } +} + +const formatRepo = (props) => { + if(props.name) return props.name +} + +TagsSelect2.contextTypes = { + I18n: PropTypes.object +} \ No newline at end of file diff --git a/app/javascript/time_tables/components/TimeTableDay.js b/app/javascript/time_tables/components/TimeTableDay.js new file mode 100644 index 000000000..165c7b848 --- /dev/null +++ b/app/javascript/time_tables/components/TimeTableDay.js @@ -0,0 +1,31 @@ +import React, { PropTypes, Component } from 'react' + +export default class TimeTableDay extends Component { + constructor(props) { + super(props) + } + + render() { + return ( + + + {((this.props.value.day).charAt(0) == 'm') ? (this.props.value.day).substr(0, 2) : (this.props.value.day).charAt(0)} + + + {this.props.value.mday} + + + ) + } +} + +TimeTableDay.propTypes = { + value: PropTypes.object.isRequired, + index: PropTypes.number.isRequired, + dayTypeActive: PropTypes.bool.isRequired +} diff --git a/app/javascript/time_tables/components/Timetable.js b/app/javascript/time_tables/components/Timetable.js new file mode 100644 index 000000000..df6e6016b --- /dev/null +++ b/app/javascript/time_tables/components/Timetable.js @@ -0,0 +1,115 @@ +import React, { PropTypes, Component } from 'react' +import actions from '../actions' +import TimeTableDay from './TimeTableDay' +import PeriodsInDay from './PeriodsInDay' +import ExceptionsInDay from './ExceptionsInDay' + + +export default class Timetable extends Component { + constructor(props, context){ + super(props, context) + } + + currentDate(mFirstday, day) { + let currentMonth = mFirstday.split('-') + let twodigitsDay = day < 10 ? ('0' + day) : day + let currentDate = new Date(currentMonth[0] + '-' + currentMonth[1] + '-' + twodigitsDay) + + return currentDate + } + + render() { + if(this.props.status.isFetching == true) { + return ( +
+
+
+ ) + } else { + return ( +
+
+
+
{this.context.I18n.time_tables.synthesis}
+
+
{this.context.I18n.time_tables.edit.day_types}
+
{this.context.I18n.time_tables.edit.periods}
+
{this.context.I18n.time_tables.edit.exceptions}
+
+
+
+
+
+
+ {actions.monthName(this.props.timetable.current_periode_range)} +
+ +
+ {this.props.timetable.current_month.map((d, i) => + + )} +
+
+ + {this.props.timetable.current_month.map((d, i) => +
+ {/* day_types */} +
+ + {/* periods */} + + + {/* exceptions */} + +
+ )} +
+
+
+
+ ) + } + } +} + +Timetable.propTypes = { + metas: PropTypes.object.isRequired, + timetable: PropTypes.object.isRequired, + status: PropTypes.object.isRequired, + onDeletePeriod: PropTypes.func.isRequired, + onExcludeDateFromPeriod: PropTypes.func.isRequired, + onIncludeDateInPeriod: PropTypes.func.isRequired +} + +Timetable.contextTypes = { + I18n: PropTypes.object +} -- cgit v1.2.3 From 08b002abfb101b1edce9750231c989591e049bf7 Mon Sep 17 00:00:00 2001 From: cedricnjanga Date: Mon, 9 Oct 2017 17:14:27 +0200 Subject: Working standard webpacker config --- app/javascript/time_tables/components/TagsSelect2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/time_tables/components') diff --git a/app/javascript/time_tables/components/TagsSelect2.js b/app/javascript/time_tables/components/TagsSelect2.js index 24f473f42..22dc7aa9c 100644 --- a/app/javascript/time_tables/components/TagsSelect2.js +++ b/app/javascript/time_tables/components/TagsSelect2.js @@ -1,6 +1,6 @@ import React, { PropTypes, Component } from 'react' import _ from 'lodash' -import Select2 from 'react-select2-wrapper' +import Select2 from 'react-select2' // get JSON full path let origin = window.location.origin -- cgit v1.2.3 From 91af53dce7183146f79313df48f7e58b4d950598 Mon Sep 17 00:00:00 2001 From: cedricnjanga Date: Tue, 10 Oct 2017 01:23:01 +0200 Subject: Add plugins to webpack config --- app/javascript/time_tables/components/Navigate.js | 4 ++-- app/javascript/time_tables/components/PeriodForm.js | 4 ++-- app/javascript/time_tables/components/SaveTimetable.js | 1 - app/javascript/time_tables/components/TagsSelect2.js | 13 ++++++++----- 4 files changed, 12 insertions(+), 10 deletions(-) (limited to 'app/javascript/time_tables/components') diff --git a/app/javascript/time_tables/components/Navigate.js b/app/javascript/time_tables/components/Navigate.js index 6ae80bce0..7307d819b 100644 --- a/app/javascript/time_tables/components/Navigate.js +++ b/app/javascript/time_tables/components/Navigate.js @@ -1,5 +1,5 @@ import React, { PropTypes, Component } from 'react' -import _ from 'lodash' +import map from 'lodash/map' import actions from '../actions' export default function Navigate({ dispatch, metas, timetable, pagination, status, filters}) { @@ -30,7 +30,7 @@ export default function Navigate({ dispatch, metas, timetable, pagination, statu className='dropdown-menu' aria-labelledby='date_selector' > - {_.map(pagination.periode_range, (month, i) => ( + {map(pagination.periode_range, (month, i) => (
  • diff --git a/app/javascript/time_tables/components/SaveTimetable.js b/app/javascript/time_tables/components/SaveTimetable.js index 0dffc7936..d5a57bd1c 100644 --- a/app/javascript/time_tables/components/SaveTimetable.js +++ b/app/javascript/time_tables/components/SaveTimetable.js @@ -1,5 +1,4 @@ import React, { PropTypes, Component } from 'react' -import _ from 'lodash' import actions from '../actions' export default class SaveTimetable extends Component{ diff --git a/app/javascript/time_tables/components/TagsSelect2.js b/app/javascript/time_tables/components/TagsSelect2.js index 22dc7aa9c..70a748a04 100644 --- a/app/javascript/time_tables/components/TagsSelect2.js +++ b/app/javascript/time_tables/components/TagsSelect2.js @@ -1,5 +1,8 @@ import React, { PropTypes, Component } from 'react' -import _ from 'lodash' +import mapKeys from 'lodash/mapKeys' +import map from 'lodash/map' +import filter from 'lodash/filter' +import assign from 'lodash/assign' import Select2 from 'react-select2' // get JSON full path @@ -13,7 +16,7 @@ export default class TagsSelect2 extends Component { mapKeys(array){ return array.map((item) => - _.mapKeys(item, (v, k) => + mapKeys(item, (v, k) => ((k == 'name') ? 'text' : k) ) ) @@ -22,7 +25,7 @@ export default class TagsSelect2 extends Component { render() { return ( this.props.onSelect2Tags(e)} onUnselect={(e) => setTimeout( () => this.props.onUnselect2Tags(e, 150))} @@ -47,10 +50,10 @@ export default class TagsSelect2 extends Component { }; }, processResults: function(data, params) { - let items = _.filter(data, ({name}) => name.includes(params.term) ) + let items = filter(data, ({name}) => name.includes(params.term) ) return { results: items.map( - item => _.assign( + item => assign( {}, item, {text: item.name} -- cgit v1.2.3