Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
j_platform / app / assets / javascripts / j_platform / clients.js.coffee
Size: Mime:
class TabOperator
  # Auto-loads the tab content based on URL hash value
  # If none is present, assume it to be first tab (found)
  parseLink: ->
    # social_account_cache_key supplied on callback from Facebook
    # In this case show accounts tab automatically
    cache_key = $.url('?social_account_cache_key')
    if $.url("?tab")? || cache_key != null && cache_key.length
      $page = $(".client-card")
      tab = "accounts"
      onSuccessCallback = onInitialTabDataLoad
    else
      url = $.url().split("#")
      if url.length > 2 # we have project and tab
        $page = $("##{url[1]}")
        tab = "#{url[2]}"
      else if url.length == 2
        $page = $(".client-card")
        tab = "#{url[1]}"
      else
        # nothing found! let's just hack it to work...
        $page = $(".client-card")
        tab = "members"

    # if parsed selected card IS the selected card, reload tab only, otherwise,
    # replace page
    if $page.attr('id') == $(".client-card.selected, .project-card.selected").attr('id')
      $tab = $(".clients-tabs .nav-tabs .#{tab} a")
      @loadTab($tab, onSuccessCallback)
    else
      $(".client-card, .project-card").removeClass('selected')
      $page.addClass('selected')
      @replacePage($page, tab)

  # Replace entire tab page, such as when switching from client to project. If
  # a tab is specified, enabled such tab after replacing page. Otherwise, load
  # first page.
  replacePage: (selectedCard, tab) ->
    selectedCardLink = selectedCard.children("a.card-link")
    $.ajax
      url: selectedCardLink.attr("href")
      context: $(".clients-tabs")
      success: (data) ->
        ($ @).replaceWith(data)
        if tab
          $tab = $(".clients-tabs .nav-tabs .#{tab} a")
        else
          $tab = $(".clients-tabs .nav-tabs li a").first()
        window.tabOperator.loadTab($tab)

  # Load content into tab, if a callback is provided, call callback
  loadTab: ($tab, onSuccessCallback) ->
    $(".clients-tabs .nav-tabs li").removeClass('active')
    $(".clients-tabs .tab-pane").removeClass('active')
    $tab.parent().addClass('active')
    $($tab.attr("href")).addClass('active')
    url = $tab.data("uri")
    targetId = $tab.attr("href")
    $target = $(targetId)
    $.ajax
      url: url
      context: $target
      success: (data) ->
        $(this).html(data)
        cardFilter.rearrangeCards()
        cardFilter.showHideCardSection()
        hideClosedClientActions()
        window.enableChosen()
        window.svgFill()
        window.enableTooltip()

        if onSuccessCallback
          onSuccessCallback($target)
        firstTimeValidation()

modifiedFacebookSocialAccounts = false

toggleAccountConnection = (e) ->
  $btn = $(@)
  $accountDiv = $btn.parents('.facebook-account-selectable').first()
  originAccountID = $accountDiv.data('originAccountId').toString()
  clientID = $accountDiv.data('clientId')
  data = {'authenticity_token': $accountDiv.data('authenticityToken')}
  isConnect = $btn.hasClass('connect-button')
  $btn.removeAttr('data-spinner-color')
  if $btn.hasClass('disconnect-button') then $btn.attr('data-spinner-color', '#717171')
  if isConnect
    url = "/admin/clients/#{clientID}/social_accounts"
    method = "POST"
    data['key'] = $accountDiv.data('key')
  else
    id = $accountDiv.data('id')
    url = "/admin/social_accounts/#{id}"
    data['client_id'] = clientID
    method = "DELETE"

  $.ajax
    url: url,
    method: method,
    data: data,
    success: (data) ->
      modifiedFacebookSocialAccounts = true
      if isConnect
        $btn.removeClass('connect-button').addClass('disconnect-button')
        $.each data, (i, val) ->
          if val.type.indexOf("Facebook") != -1 and val.origin_id_str == originAccountID
            $accountDiv.data('id', val.id)
            return false # break
      else
        $btn.removeClass('disconnect-button').addClass('connect-button')
    error: (jqXHR, textStatus, errorThrown) ->
      data = JSON.parse(jqXHR.responseText)
      noty
        text: data.notice
        type: 'error'
    complete: ->
      removeButtonSpinner()

onFacebookModalShown = ->
  $('#facebook-account-select').on('click', '.connection-button:not(.hide-button-text)', toggleAccountConnection)

$(document).on "hidden.bs.modal", "#facebook-account-select", (e) ->
  if modifiedFacebookSocialAccounts
    noty
      text: "Successfully modified account."
      type: 'success'
    setTimeout 'updateCardCount()', 500

activateClientCardActions = ->
  $("#btn-new-client").click (e) ->
    e.preventDefault()
    $.ajax
      url: ($ @).attr("href"),
      method: "get",
      success: (data) ->
        JugnooUtils.loadModal($("#modal-new-client"), data)
        $("#modal-new-client").modal('show')
        enableChosen()
        validateAvatarFileType()
        $("#modal-new-client").on "shown.bs.modal", ->
          $('.new_client').enableClientSideValidations().resetClientSideValidations()
      complete: ->
        removeButtonSpinner()

$(document).on "page:change", ->
  if $(".clients-index").length
    resetCardClick()

$(document).on "page:change", ->
  if $(".clients-index, .clients-show").length
    activateClientCardClick()
    activateClientCardActions()

activateClientCardClick = ->
  $(".client-card").click (e) ->
    self = ($ @)
    unless self.hasClass('closed')
      if e.target.tagName != "A" && e.target.tagName != "FOOTER" && $(e.target).closest("footer").length == 0 && !self.hasClass('selected')
        $(".card").removeClass("selected card-hover-state")
        self.addClass("selected")
        window.svgFill()
        Turbolinks.visit self.find(".card-link").attr("href")
  cardFilter.rearrangeCards('status')

$(document).on "click", ".client-card .edit-link", (e) ->
  e.preventDefault()
  $.ajax
    url: ($ @).attr("href"),
    success: (data) ->
      JugnooUtils.loadModal($("#modal-edit-client"), data)
      $("#modal-edit-client").modal('show')
      enableChosen()
      validateAvatarFileType()
      $("#modal-edit-client").on "shown.bs.modal", ->
        $('.edit_client').enableClientSideValidations().resetClientSideValidations()

$(document).on "ajax:success", ".client-card .suspend-link, .client-card .reactivate-link, .client-card .close-link", (e, data) ->
  if $(".clients-show").length
    _replaceData = $(data).findOrFilter('#client-sidebar')
    back_url = $('.clients-show .btn-back').attr('href')
    if _replaceData.length == 0
      $(location).attr('href', back_url)
    else
      $('#client-sidebar').jReplaceHtml(_replaceData)
      updateClientCard()
      enableCardOptions()
  else if $(".clients-index").length
    updateClientIndexCard(e, data)

  window.svgFill()

###*
 * updateClientIndexCard function to update client card in index page
 * @param  {event} e
 * @param  {string} data
###
updateClientIndexCard = (e, data) ->
  $data = $(data).findOrFilter('.client-card')
                 .removeClass('selected arrow')
  card = $(e.target).closest('.card')
  parentContainer = card.closest('.card-group')
  card.remove()
  unless $(e.target).hasClass('close-link')
    parentContainer.prepend($data)
  cardFilter.rearrangeCards('status')
  showActionNoty($data)
  activateClientCardClick()

###*
 * updateClientCard
 * updating client card with new ajax data
###
updateClientCard = ->
  card = $('.client-card')
  showActionNoty(card)
  cardFilter.rearrangeCards('status')

###*
 * enableCardOptions
 * enables multiple options
###
enableCardOptions = ->
  activateClientCardActions()
  enableCardClick()
  sortProjectCard()
  firstTimeValidation()
  projectSearchMessage()
  enableTooltip()

showActionNoty = (card) ->
  isSuspended = card.find('.status.suspended')
  isReactivate = card.find('.status.active')
  isClosed = card.find('.status.closed')
  if isSuspended.length
    hideClosedClientActions()
    if $('#btn-new-project').length then $('#btn-new-project, .dummy-card.project-card').addClass('prevent disabled')
  if isClosed.length
    if $(".clients-show").length
      hideClosedClientActions()
      $(location).attr "href", $('.btn-back').attr('href')
    else
      hideClosedClientActions()
  if isReactivate.length
    showActiveClientActions()

onInitialTabDataLoad = ($target) ->
  $target.find(".add-list").css("height", 0)
  tab = $target.data('tab')
  notice = $.url('?notice')
  if notice?.length
    noty
      text: unescape(notice)
      type: 'error'
  window.pushPath($.url().replace("&type=failure&notice=#{notice}", ""))

  if location.hash.indexOf("#accounts") > -1 and $target.data('facebookModalShown') != true
    $accountSelectDiv = $('#facebook-account-select').first()
    if $accountSelectDiv.length > 0
      $accountSelectDiv.on('shown.bs.modal', onFacebookModalShown).on('hide.bs.modal', ->
        $target.data('facebookModalShown', true)
        $tab = $(".clients-tabs .nav-tabs .#{tab} a")
        window.tabOperator.loadTab($tab)
      )
      $accountSelectDiv.modal()
      $accountSelectDiv.on 'hide.bs.modal', ->
        window.removeParameterFromLocation("social_account_cache_key")

  location.hash = "#{$target.data('tab')}"

@pushPath = (path) ->
  if typeof (window.history.pushState) is "function"
    window.history.pushState null, path, path
  else if ($("html.ie9, html.lt-ie9").length is 0) # Browser is not IE9 or lower
    window.location.hash = "#!" + path

# derived from LukePH's answer @ http://stackoverflow.com/questions/1634748/how-can-i-delete-a-query-string-parameter-in-javascript?rq=1
@removeParameterFromURL = (url, parameter) ->
  urlHashParts = url.split('#')
  urlparts = urlHashParts[0].split('?')
  if urlparts.length >= 2
    urlBase = urlparts.shift()                    # get first part, and remove from array
    queryString = urlparts.join("?");             # join it back up
    prefix = encodeURIComponent(parameter) + '='
    pars = queryString.split(/[&;]/g)
    for i in [pars.length-1..0] by -1             # reverse iteration as may be destructive
      if pars[i].lastIndexOf(prefix, 0) != -1     # idiom for string.startsWith
        pars.splice(i, 1)
    url = "#{urlBase}?#{pars.join('&')}"
  if urlHashParts.length > 1
    url += "##{urlHashParts.slice(1).join('#')}"
  url

@removeParameterFromLocation = (key) ->
  newURL = window.removeParameterFromURL(window.location.href, key)
  window.pushPath newURL

@tabOperator = new TabOperator

$(document).on "page:change", ->
  if $(".clients-show").length > 0
    tabOperator.parseLink()
    showActiveProjectTab()
    projectSearchMessage()
    showNoProjectMessage()
    # Wire up card click behaviour
    enableCardClick()
    hideClosedClientActions()
    sortProjectCard()

###*
 * Click Handler for dummy card
 * This will open the add social account menu or queues, members, projects options.
###
$(document).on "click", ".dummy-card", (e) ->
  e.preventDefault()
  $this = $ @
  if($this.hasClass("project-card"))
    $("#btn-new-project").trigger "click"
  else
    ###*
     * Stop propagation to prevent the menu from hiding due to loss of focus.
    ###
    e.stopPropagation();
    $this.closest(".tab-pane").find(".tab-controls-bar button").trigger "click"

# Wire up tab click behaviour, this must be wired at document level as
# tab page could be completely replaced
$(document).on "click", ".clients-tabs .nav-tabs a", (e) ->
  e.preventDefault()
  $this = $ @

  # We push the url into browser history for back button compatibility
  if /project/i.test($.url("#"))
    path = "#" + $.url("#") + "#" + $this.data("source")
  else
    path = "#" + $this.data("source")

  window.pushPath(path)
  window.tabOperator.loadTab($ @)

$(window).on "hashchange", ->
  if $(".clients-show").length > 0
    tabOperator.parseLink()

pageCards = ->
  $(".card.client-card")

searchField = ->
  $("#filter_filter_chosen .chosen-results").first().find('.result-selected')

$(document).on "keyup", ".clients-index input.filter", (e) ->
  if $('body.clients-index').length
    options = {}
    $('.filtered-out-content').removeClass('filtered-out-content')
    options = {highlight: false, missClass: "filtered-out-content", cellClasses: ["role", "name"]}

    $("#main").filterBy($(this).val(), options)
    cardFilter.showHideCardSection()

$(document).ready ->
  pageCards().addClass('table-row')

handleClientFormSuccess = ->
  location.reload()

handleClientFormErrors = (new_edit, data) ->
  try
    success = JSON.parse(data.responseText)
    handleClientFormSuccess()
  catch
    replaceClientForm(new_edit, data)

replaceClientForm = (new_edit, data) ->
  $("#modal-#{new_edit}-client .modal-body").html($(data.responseText).find('.modal-body').html());
  enableChosen()
  validateAvatarFileType()
  $('.'+new_edit+'_client').enableClientSideValidations()

$(document).on "ajax:success", "#new_client, .edit_client", (e, data) ->
  if data.status == "success"
    handleClientFormSuccess()

$(document).on "ajax:error", "#new_client", (e, data) ->
  handleClientFormErrors 'new', data

$(document).on "ajax:error", ".edit_client", (e, data) ->
  handleClientFormErrors 'edit', data

# Enabling Card Click function
@enableCardClick = ->
  $(".client-card:not(.dummy-card), .project-card:not(.dummy-card)").click (e) ->
    e.preventDefault()
    $this = $ @
    if e.target.tagName != "A" && e.target.tagName != "FOOTER" && $(e.target).closest("footer").length == 0 && !$this.hasClass('selected')
      $(".card").removeClass("selected card-hover-state")
      $this.addClass("selected")
      window.svgFill()
      window.pushPath($this.children(".card-link").data("href"))
      window.tabOperator.replacePage($this)

@resetCardClick = ->
  $(".card").removeClass("selected card-hover-state")
  window.svgFill()

hideClosedClientActions = ->
  if $('.clients-show').length
    if $('.client-card .status.closed, .client-card .status.suspended').length
      actionBtns = $('#btn-new-project, .attach-button, #btn-manage-resolutions, .btn-manage-resolutions, .dummy-card, .btn-new-queue, #btn-toggle-social-accounts')

      # Remember which were already disabled:
      actionBtns.filter('.prevent.disabled').attr('previouslyDisabled', true)
      actionBtns.addClass('prevent disabled')
      $('.card:not(.client-card) .dropdown').hide()

showActiveClientActions = ->
  if $('.clients-show').length
    actionBtns = $('#btn-new-project, .attach-button, #btn-manage-resolutions, .btn-manage-resolutions, .dummy-card, .btn-new-queue, #btn-toggle-social-accounts')
    # Only re-enable ones that aren't previously diabled...
    actionBtns.not('[previouslyDisabled=true]').removeClass('prevent disabled')
    $('.card .dropdown').show()

###*
 * Switching tab accroding to active project
 * If we switch project from active to suspended then swithing tab to suspended
###
@showActiveProjectTab = ->
  selectedProjectCard = $('#client-sidebar .projects-container').find('.card.selected')
  if selectedProjectCard.length
    if selectedProjectCard.hasClass('active')
      $('#project-list-filter .btn-active').click()
    else if selectedProjectCard.hasClass('suspended')
      $('#project-list-filter .btn-suspended').click()
    else if selectedProjectCard.hasClass('closed')
      $('#project-list-filter .btn-closed').click()

###*
 * If there are no project in tab then showing info message
 * - "You have no suspended/closed project."
###
@showNoProjectMessage = ->
  projectContainer = $('.projects-container')
  suspendedProjects = projectContainer.find('#suspended-cards .card').length
  closedProjects = projectContainer.find('#closed-cards .card').length
  projectContainer.find('#suspended-cards .no-item-message').toggle(!suspendedProjects)
  projectContainer.find('#closed-cards .no-item-message').toggle(!closedProjects)

###*
 * Showing search info message on project search
###
@projectSearchMessage = ->
  projectContainer = $('.projects-container .card-group:not(.hide)')
  if projectContainer.length
    $_allCards = projectContainer.find('.card:not(.dummy-card)')
    $_hiddenCards = $_allCards.filter('.filtered-out-content')
    if $_allCards.length == 0
      $('#search-project').attr('disabled', 'disabled').addClass('disabled')
    else
      $("#client-sidebar .no-result-message").toggle($_allCards.length == $_hiddenCards.length)
      $('#search-project').removeAttr('disabled').removeClass('disabled')

@sortProjectCard = ->
  $('.projects-container .card-group').each ->
    $(this).sortChildren({childSelector: '.card'})

$(document).on "keyup", ".clients-show #search-project", (e) ->
  options = {}
  $_cardGroups = $(".projects-container .card-group")
  $_cards = $_cardGroups.find('.card:not(.dummy-card)')
  $_cards.removeClass('filtered-out-content')
  options = {highlight: false, missClass: "filtered-out-content", cellClasses: ["name"]}
  $_cardGroups.filterBy($(this).val(), options)
  projectSearchMessage()

$(document).on "click", "#client-sidebar .btn-group .btn", (e) ->
  e.preventDefault()
  $_this = $(@)
  $_searxhBox = $(".clients-show #search-project")
  cardContainer = $("#client-sidebar .projects-container")
  cardContainer.find('.card-group').addClass('hide')

  if $_this.hasClass('btn-active')
    cardContainer.find('#active-cards').removeClass('hide')
  else if $_this.hasClass('btn-suspended')
    cardContainer.find('#suspended-cards').removeClass('hide')
  else if $_this.hasClass('btn-closed')
    cardContainer.find('#closed-cards').removeClass('hide')
  $_searxhBox.val ""
  $_searxhBox.keyup()
  $('.projects-container .no-result-message').hide()
  showNoProjectMessage()
  sortProjectCard()

$(document).on "click", "#client-avatar .avatar-upload-link, #avatar-preview", (e) ->
  e.preventDefault()
  $('#client-avatar .client-avatar-upload').click()

$(document).on "keydown", "#client_name, .client_admin_ids",  (e) ->
  if (e.keyCode == 13) #if enter pressed in #client_name, do not close modal
    e.preventDefault()

$(document).on "click", ".account-card .dropdown-menu li > a, #social-accounts-options li > a.facebook", (e) ->
  $link = $(@)
  oldURL = $link.attr('href')
  # Only need to do this if this is for adding / resetting a Facebook account
  # If adding: check it has class 'facebook'. If resetting: ensure card contains a 'facebook' icon and the 'reset' option was selected (i.e. not delete)
  requiresFBLogout = $link.hasClass('facebook') && $link.parents('#social-accounts-options').length > 0
  requiresFBLogout or= oldURL.indexOf("edit") != -1 && $link.parents('.account-card').find('.facebook, .facebook-page').length > 0
  if requiresFBLogout
    e.preventDefault()
    FB.getLoginStatus()
    FB.getLoginStatus (response) ->
      if (response.status == 'connected')
        accessToken = response.authResponse.accessToken
        $link.attr('href', "#{oldURL}#{if oldURL.indexOf('?') == -1 then '?' else '&'}fb_access_token=#{accessToken}")
      window.location = $link.attr('href')