amatriain/feedbunch

View on GitHub
FeedBunch-app/app/assets/javascripts/ng-services/ng-TourSvc.js.coffee.erb

Summary

Maintainability
Test Coverage
########################################################
# AngularJS service to show application tours
########################################################

angular.module('feedbunch').service 'tourSvc',
['$rootScope', '$timeout', 'csrfTokenSvc', 'timerFlagSvc',
($rootScope, $timeout, csrfTokenSvc, timerFlagSvc)->

  #--------------------------------------------
  # Media query to show the main app tour only in screens bigger than a smartphone
  #--------------------------------------------
  sm_min_media_query = 'screen and (min-width: 768px)'

  #--------------------------------------------
  # Media query to show the mobile app tour only in smartphone-sized screens
  #--------------------------------------------
  xs_max_media_query = 'screen and (max-width: 768px)'

  # Constants for the different tour URL fragments
  TOURS = {main_tour: 'main', mobile_tour: 'mobile', feed_tour: 'feed', entry_tour: 'entry', kb_shortcuts_tour: 'kb_shortcuts'}

  # Constants for the different operations the web worker can perform
  LOAD_TOUR = 'load_tour'
  HIDE_TOUR = 'hide_tour'
  RESET_TOURS = 'reset_tours'

  # CSRF token
  token = csrfTokenSvc.get_token()

  # Web worker to load or hide tours
  worker = new Worker '<%= asset_path 'workers/tours_worker' %>'
  worker.onmessage = (e) ->
    if e.data.status == 200 || e.data.status == 304
      if e.data.operation == LOAD_TOUR
        tour_loaded e.data.response
      else if e.data.operation == RESET_TOURS
        timerFlagSvc.start 'success_reset_tours'
    else if e.data.status == 401 || e.data.status == 422
      $window.location.href = '/login'
    else
      if e.data.operation == LOAD_TOUR
        timerFlagSvc.start 'error_loading_tour'
      else if e.data.operation == HIDE_TOUR
        timerFlagSvc.start 'error_changing_show_tour'
      else if e.data.operation == RESET_TOURS
        timerFlagSvc.start 'error_changing_show_tour'
    $rootScope.$digest()

  #--------------------------------------------
  # PRIVATE FUNCTION: Operations after a tour has been loaded
  #--------------------------------------------
  tour_loaded = (response)->
    if response.tour == TOURS.main_tour
      delay = 0
      tour =
        id: 'main-tour',
        onEnd: main_tour_end,
        onClose: main_tour_end
    else if response.tour == TOURS.mobile_tour
      delay = 0
      tour =
        id: 'mobile-tour',
        onEnd: hide_mobile_tour,
        onClose: hide_mobile_tour
    else if response.tour == TOURS.feed_tour
      delay = 0
      tour =
        id: 'feed-tour',
        onEnd: hide_feed_tour,
        onClose: hide_feed_tour
    else if response.tour == TOURS.entry_tour
      # Show entry tour after a 600ms delay, to give entry open/autoscroll
      # animation time to finish.
      delay = 600
      tour =
        id: 'entry-tour',
        onEnd: hide_entry_tour,
        onClose: hide_entry_tour
    else if response.tour == TOURS.kb_shortcuts_tour
      delay = 0
      tour =
        id: 'kb_shortcuts-tour',
        onEnd: hide_kb_shortcuts_tour,
        onClose: hide_kb_shortcuts_tour
    tour.showCloseButton = true
    tour.showPrevButton = false
    tour.showNextButton = true
    tour.i18n = response.i18n
    tour.steps = response.steps
    $timeout ->
      hopscotch.startTour tour
    , delay

  #--------------------------------------------
  # PRIVATE FUNCTION: set to false the show_main_tour flag for the current user.
  #--------------------------------------------
  hide_main_tour = ->
    $rootScope.show_main_tour = false
    worker.postMessage {operation: HIDE_TOUR, token: token, show_main_tour: 'false'}

  #--------------------------------------------
  # PRIVATE FUNCTION: set to false the show_mobile_tour flag for the current user.
  #--------------------------------------------
  hide_mobile_tour = ->
    $rootScope.show_mobile_tour = false
    worker.postMessage {operation: HIDE_TOUR, token: token, show_mobile_tour: 'false'}

  #--------------------------------------------
  # PRIVATE FUNCTION: set to false the show_feed_tour flag for the current user.
  #--------------------------------------------
  hide_feed_tour = ->
    $rootScope.show_feed_tour = false
    worker.postMessage {operation: HIDE_TOUR, token: token, show_feed_tour: 'false'}

  #--------------------------------------------
  # PRIVATE FUNCTION: set to false the show_entry_tour flag for the current user.
  #--------------------------------------------
  hide_entry_tour = ->
    $rootScope.show_entry_tour = false
    worker.postMessage {operation: HIDE_TOUR, token: token, show_entry_tour: 'false'}

  #--------------------------------------------
  # PRIVATE FUNCTION: set to false the show_kb_shortcuts_tour flag for the current user.
  #--------------------------------------------
  hide_kb_shortcuts_tour = ->
    $rootScope.show_kb_shortcuts_tour = false
    worker.postMessage {operation: HIDE_TOUR, token: token, show_kb_shortcuts_tour: 'false'}

  #---------------------------------------------
  # PRIVATE FUNCTION: show the main application tour.
  #---------------------------------------------
  show_main_tour = ->
    # Show the main application tour, if the show_main_tour flag is true
    if $rootScope.show_main_tour
      # The main tour is only shown in screens bigger than a smartphone
      enquire.register sm_min_media_query, ->
        worker.postMessage {operation: LOAD_TOUR, token: token, tour: TOURS.main_tour}

  #---------------------------------------------
  # PRIVATE FUNCTION: show the keyboard shortcuts application tour.
  #---------------------------------------------
  show_kb_shortcuts_tour = ->
    # If main tour is completed, kb shortcuts tour is shown as soon as page is loaded (unless already completed too)
    if !$rootScope.show_main_tour && $rootScope.show_kb_shortcuts_tour
      # The keyboards shortcuts tour is only shown in screens bigger than a smartphone
      enquire.register sm_min_media_query, ->
        worker.postMessage {operation: LOAD_TOUR, token: token, tour: TOURS.kb_shortcuts_tour}

  #---------------------------------------------
  # PRIVATE FUNCTION: show the mobile application tour.
  #---------------------------------------------
  show_mobile_tour = ->
    if $rootScope.show_mobile_tour
      # The mobile tour is only shown in smartphone-sized screens
      enquire.register xs_max_media_query, ->
        worker.postMessage {operation: LOAD_TOUR, token: token, tour: TOURS.mobile_tour}

  #--------------------------------------------
  # PRIVATE FUNCTION: at the end of main tour, mark show_main_tour flag to false so it's not shown again; and if the
  # show_kb_shortcuts_flag is set to true, show the keyboard shortcuts tour
  #--------------------------------------------
  main_tour_end = ->
    hide_main_tour()
    show_kb_shortcuts_tour() if $rootScope.show_kb_shortcuts_tour

  service =

    #---------------------------------------------
    # Show tours if the appropiate user config flags are set to true, when the page finishes loading:
    # - main tour (only for screens bigger than smartphones)
    # - keyboard shortcuts tour (only for screens bigger than smartphones, and only if the main tour is already completed)
    # - mobile tour (only for smartphone-sized screens)
    #---------------------------------------------
    start: ->
      show_main_tour()
      show_kb_shortcuts_tour()
      show_mobile_tour()

    #---------------------------------------------
    # Show the main application tour.
    #---------------------------------------------
    show_main_tour: show_main_tour

    #---------------------------------------------
    # Show the keyboard shortcuts application tour.
    #---------------------------------------------
    show_kb_shortcuts_tour: show_kb_shortcuts_tour

    #---------------------------------------------
    # Show the mobile application tour.
    #---------------------------------------------
    show_mobile_tour: show_mobile_tour

    #---------------------------------------------
    # Show the feed application tour.
    #---------------------------------------------
    show_feed_tour: ->
      if $rootScope.show_feed_tour
        # The feed tour is only shown in screens bigger than a smartphone
        enquire.register sm_min_media_query, ->
          worker.postMessage {operation: LOAD_TOUR, token: token, tour: TOURS.feed_tour}

    #---------------------------------------------
    # Show the entry application tour.
    #---------------------------------------------
    show_entry_tour: ->
      if $rootScope.show_entry_tour
        worker.postMessage {operation: LOAD_TOUR, token: token, tour: TOURS.entry_tour}

    #---------------------------------------------
    # Reset all application tours, so that they are shown again from the beginning.
    #---------------------------------------------
    reset_tours: ->
      $rootScope.show_main_tour = true
      $rootScope.show_mobile_tour = true
      $rootScope.show_feed_tour = true
      $rootScope.show_entry_tour = true
      $rootScope.show_kb_shortcuts_tour = true
      worker.postMessage {operation: RESET_TOURS, token: token}

  return service

]