From a9e346ffb36eec92da15bce55a18201aeab6cdae Mon Sep 17 00:00:00 2001 From: Seth Call Date: Wed, 18 May 2016 15:18:38 -0500 Subject: [PATCH] VRFS-4061 - Implement more obvious way to join a lesson when it's time to join --- .../assets/javascripts/lesson_utils.js.coffee | 39 +++++++++++++ .../assets/javascripts/react-components.js | 1 + .../InLessonBroadcast.js.jsx.coffee | 1 - .../JamClassScreen.js.jsx.coffee | 32 ++++++++++- .../LessonBookingDecision.js.jsx.coffee | 4 ++ .../actions/LessonTimerActions.js.coffee | 6 ++ .../stores/BroadcastStore.js.coffee | 26 +-------- .../stores/LessonTimerStore.js.coffee | 55 +++++++++++++++++++ 8 files changed, 137 insertions(+), 27 deletions(-) create mode 100644 web/app/assets/javascripts/lesson_utils.js.coffee create mode 100644 web/app/assets/javascripts/react-components/actions/LessonTimerActions.js.coffee create mode 100644 web/app/assets/javascripts/react-components/stores/LessonTimerStore.js.coffee diff --git a/web/app/assets/javascripts/lesson_utils.js.coffee b/web/app/assets/javascripts/lesson_utils.js.coffee new file mode 100644 index 000000000..d8a8d67ae --- /dev/null +++ b/web/app/assets/javascripts/lesson_utils.js.coffee @@ -0,0 +1,39 @@ +# +# Common utility functions. +# + +$ = jQuery +context = window +context.JK ||= {}; + +class LessonUtils + constructor: () -> + @logger = context.JK.logger + + init: () => + + getTimeRemaining: (endtime) -> + t = new Date(endtime).getTime() - new Date().getTime() + + originalT = t + + if t < 0 + seconds = Math.ceil( (t/1000) % 60 ); + minutes = Math.ceil( (t/1000/60) % 60 ); + hours = Math.ceil( (t/(1000*60*60)) % 24 ); + days = Math.ceil( t/(1000*60*60*24) ); + else + seconds = Math.floor( (t/1000) % 60 ); + minutes = Math.floor( (t/1000/60) % 60 ); + hours = Math.floor( (t/(1000*60*60)) % 24 ); + days = Math.floor( t/(1000*60*60*24) ); + + return { + 'total': originalT, + 'days': days, + 'hours': hours, + 'minutes': minutes, + 'seconds': seconds + }; +# global instance +context.JK.LessonUtils = new LessonUtils() \ No newline at end of file diff --git a/web/app/assets/javascripts/react-components.js b/web/app/assets/javascripts/react-components.js index c8f7b2fb0..5e3fb6c53 100644 --- a/web/app/assets/javascripts/react-components.js +++ b/web/app/assets/javascripts/react-components.js @@ -6,6 +6,7 @@ //= require ./react-components/stores/NavStore //= require ./react-components/stores/UserStore //= require ./react-components/stores/UserActivityStore +//= require ./react-components/stores/LessonTimerStore //= require ./react-components/stores/SchoolStore //= require ./react-components/stores/StripeStore //= require ./react-components/stores/AvatarStore diff --git a/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee b/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee index fc85530ab..cccbe2b29 100644 --- a/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/InLessonBroadcast.js.jsx.coffee @@ -43,7 +43,6 @@ context = window timeString render: () -> - console.log("@props.lessonSession", @props.lessonSession) if @props.lessonSession.completed if @props.lessonSession.success content = `
diff --git a/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee b/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee index d9f78a228..f45d34819 100644 --- a/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/JamClassScreen.js.jsx.coffee @@ -3,6 +3,8 @@ rest = context.JK.Rest() logger = context.JK.logger UserStore = context.UserStore +LessonTimerStore = context.LessonTimerStore +LessonTimerActions = context.LessonTimerActions @JamClassScreen = React.createClass({ @@ -10,7 +12,8 @@ UserStore = context.UserStore @ICheckMixin, @PostProcessorMixin, Reflux.listenTo(AppStore, "onAppInit"), - Reflux.listenTo(UserStore, "onUserChanged") + Reflux.listenTo(UserStore, "onUserChanged"), + Reflux.listenTo(LessonTimerStore, "onLessonTimersChanged") ] lookup : { @@ -38,9 +41,20 @@ UserStore = context.UserStore onUserChanged: (userState) -> @setState({user: userState?.user}) + onLessonTimersChanged: (lessons) -> + @setState({lessonTimes: lessons}) + componentDidMount: () -> @root = $(@getDOMNode()) + componentWillUpdate: (nextProps, nextState) -> + # associate time info from LessonTimerStore with our lesson info + if nextState.lessonTimes? && nextState.lesson_sessions?.entries? + for lesson in nextState.lesson_sessions.entries + lessonWithTime = nextState.lessonTimes[lesson.id] + if lessonWithTime? + lesson.times = lessonWithTime.times + componentDidUpdate: () -> items = @root.find('.jamtable tbody td.actionsColumn .lesson-session-actions-btn') @@ -221,6 +235,7 @@ UserStore = context.UserStore @postProcess(response) + LessonTimerActions.loadLessons(response) @setState({lesson_sessions: response}) failedJamClassLoad: (jqXHR) -> @@ -410,9 +425,22 @@ UserStore = context.UserStore unreadMessages = `` else unreadMessages = null + + timeStmt = lessonData.music_session.pretty_scheduled_start_with_timezone + + if lessonData.times? + if lessonData.times.startingSoon + timeStmt = "Starts in #{lessonData.times.until.minutes} minutes" + else if lessonData.times.initialWindow + minutes = -lessonData.times.until.minutes + + if minutes == 1 + timeStmt = "This lesson just started. Join now!" + else + timeStmt = "Started #{minutes} minutes ago. Join now!" lesson = `
{lessonData.other.first_name}
{lessonData.other.last_name}
- {lessonData.music_session.pretty_scheduled_start_with_timezone} + {timeStmt} {lessonData.displayStatus} {unreadMessages} menu
diff --git a/web/app/assets/javascripts/react-components/LessonBookingDecision.js.jsx.coffee b/web/app/assets/javascripts/react-components/LessonBookingDecision.js.jsx.coffee index 1ede418fd..f7cd658a2 100644 --- a/web/app/assets/javascripts/react-components/LessonBookingDecision.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/LessonBookingDecision.js.jsx.coffee @@ -74,9 +74,13 @@ if name == 'slot-decision' value = $(e.target).val() + logger.debug("LessonBookingDecision: slot-decision made with value: " + value) + + @setState({slot_decision: value}) @props.onSlotDecision({slot_decision: value}) else if name == 'update-all' checked = $(e.target).is(':checked') + logger.debug("LessonBookingDecision: update-all changed: " + checked) @props.onUpdateAllDecision({update_all: checked}) else throw "checkbox changed with unknown name #{name}" diff --git a/web/app/assets/javascripts/react-components/actions/LessonTimerActions.js.coffee b/web/app/assets/javascripts/react-components/actions/LessonTimerActions.js.coffee new file mode 100644 index 000000000..bf812cc97 --- /dev/null +++ b/web/app/assets/javascripts/react-components/actions/LessonTimerActions.js.coffee @@ -0,0 +1,6 @@ +context = window + +@LessonTimerActions = Reflux.createActions({ + loadLessons: {} +}) + diff --git a/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee b/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee index fb5f69aab..150b4f939 100644 --- a/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee +++ b/web/app/assets/javascripts/react-components/stores/BroadcastStore.js.coffee @@ -21,32 +21,10 @@ BroadcastStore = Reflux.createStore( this.listenTo(context.AppStore, this.onAppInit) this.listenTo(context.SessionStore, this.onSessionChange) this.listenTo(context.NavStore, this.onNavChange) + @lessonUtils = context.JK.LessonUtils onAppInit: (@app) -> - getTimeRemaining: (endtime) -> - t = new Date(endtime).getTime() - new Date().getTime() - - originalT = t - - if t < 0 - seconds = Math.ceil( (t/1000) % 60 ); - minutes = Math.ceil( (t/1000/60) % 60 ); - hours = Math.ceil( (t/(1000*60*60)) % 24 ); - days = Math.ceil( t/(1000*60*60*24) ); - else - seconds = Math.floor( (t/1000) % 60 ); - minutes = Math.floor( (t/1000/60) % 60 ); - hours = Math.floor( (t/(1000*60*60)) % 24 ); - days = Math.floor( t/(1000*60*60*24) ); - - return { - 'total': originalT, - 'days': days, - 'hours': hours, - 'minutes': minutes, - 'seconds': seconds - }; lessonTick: () -> @timeManagement() @@ -55,7 +33,7 @@ BroadcastStore = Reflux.createStore( timeManagement: () -> lastCheck = $.extend({}, @currentLesson) lessonSession = @currentLesson - lessonSession.until = @getTimeRemaining(lessonSession.scheduled_start) + lessonSession.until = @lessonUtils.getTimeRemaining(lessonSession.scheduled_start) if lessonSession.until.total < 0 # we are past the start time if lessonSession.until.total > -(10 * 60 * 1000) # 10 minutes diff --git a/web/app/assets/javascripts/react-components/stores/LessonTimerStore.js.coffee b/web/app/assets/javascripts/react-components/stores/LessonTimerStore.js.coffee new file mode 100644 index 000000000..dd101d0e8 --- /dev/null +++ b/web/app/assets/javascripts/react-components/stores/LessonTimerStore.js.coffee @@ -0,0 +1,55 @@ +$ = jQuery +context = window +logger = context.JK.logger +rest = new context.JK.Rest() + +@LessonTimerStore = Reflux.createStore( + { + listenables: @LessonTimerActions + lessons: {} + slowTime: 10000 + fastTime: 1000 + + init: ( ) -> + @timer() + this.listenTo(context.AppStore, this.onAppInit) + + onAppInit: (@app) -> + @lessonUtils = context.JK.LessonUtils + + timer: () -> + setInterval((() => @timeout()), @fastTime) + + onLoadLessons: (lessons) -> + for lesson in lessons?.entries + @lessons[lesson.id] = lesson + + timeout: () -> + + for id, lesson of @lessons + untilInfo = @lessonUtils.getTimeRemaining(lesson.music_session.scheduled_start) + + initialWindow = false + inThePast = false + beforeSession = false + startingSoon = false + + if untilInfo.total < 0 + # we are past the start time + if untilInfo.total > -(10 * 60 * 1000) # 10 minutes + initialWindow = true + else if untilInfo.total > -(15*60*1000) # 15 minute + inThePast = true + else + # we are before the due time + beforeSession = true + startingSoon = untilInfo.total <= (60 * 60 * 1000) # 60 minutes - 1hr until start time + + lesson.times = {until:untilInfo, initialWindow: initialWindow, beforeSession: beforeSession, startingSoon: startingSoon, inThePast: inThePast} + + @changed() + + changed:() -> + this.trigger(@lessons) + } +) \ No newline at end of file