Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- angular
- .module('CourseCommentV2')
- .controller('CourseCommentsV2Ctrl', [
- '$scope', 'gon_object', 'CourseCommentV2', '$q', '$timeout', 'Paginator', 'ZoomedPaginator',
- ($scope, gon_object, CourseCommentV2, $q, $timeout, Paginator, ZoomedPaginator) ->
- # Don't think this should be configurable
- # since this would be a huge change.
- MAX_COMMENT_LEVEL = 3
- THREAD_LEVEL = 2
- REPLY_LEVEL = 3
- # We might want this configurable but not
- # likely to change super often
- DEFAULT_PER_PAGE = 5
- DEFAULT_PAGE = 1
- $scope.STATES =
- CHRONOLOGICAL: 0
- MOST_POPULAR: 1
- ZOOMED: 2
- $scope.currentUser = gon_object.user
- # make the baseComment available immmediately and
- # merge onto it
- $scope.courseComment = {}
- $scope.expanders = {}
- $scope.forms = {}
- $scope.sortOrder = $scope.STATES.CHRONOLOGICAL
- # Keep track of asynchronous calls
- $scope.requestsWaiting = 0
- # Make sure anything relying on the nested structure isn't
- # called until the data structure is ready
- $scope.ready = false
- $scope.hasMoreComments = (id, displayState) ->
- ($scope.expanders[id] and $scope.expanders[id].isLastPage() is false) and $scope.sortState is displayState
- # This removes the comment from the within the
- # parent scope.courseComment object which contains
- # all the comments and replies that are rendered
- $scope.deleteComment = (id, parent_id) ->
- idx = undefined
- parentNode = findNode(parent_id, $scope.courseComment)
- if parentNode?
- for child, index in parentNode.children
- if child.id is id
- idx = index
- parentNode.children.splice(idx, 1) if idx?
- # Recursive find for deleting or doing something to the
- # nested children of scope.courseComment
- findNode = (id, currentNode) ->
- i = undefined
- currentChild = undefined
- result = undefined
- if id == currentNode.id
- currentNode
- else
- if currentNode.children?
- i = 0
- while i < currentNode.children.length
- currentChild = currentNode.children[i]
- # Search in the current child
- result = findNode(id, currentChild)
- # Return the result if the node has been found
- if result != false
- return result
- i += 1
- # The node has not been found and we have no more options
- false
- # Use timeout to guarantee the check of
- # requestsWaiting waits until the next event loop
- setCommentStateToReady = () ->
- $timeout ->
- if $scope.requestsWaiting is 0
- $scope.deferred.resolve($scope.courseComment)
- , 0, false
- incrementRequestsWaiting = () ->
- $scope.requestsWaiting++
- decrementRequestsWaiting = () ->
- --$scope.requestsWaiting
- addChildrenContainer = (comment) ->
- comment.children = [] unless comment.children?
- setExpanderPaginationObj = (data, responseHeaders) ->
- # check if there are children and if there are grab
- # if the level is 2 or greater it means that it is not the base
- # comment
- if data[0]? and data[0].level >= 2
- key = data[0].parent_id
- # TODO check if the key exists if it does then
- # update the attributes of the object
- # otherwise set a new paginator
- if $scope.expanders[key]?
- $scope.expanders[key].setAttributes(responseHeaders())
- else
- pageObject = new Paginator(responseHeaders())
- $scope.expanders[key] = pageObject
- setZoomedExpanderPaginationObj = (data, responseHeaders) ->
- if data? and data.course_comment? && data.course_comment.level >= 2
- data = data.course_comment
- # TODO check if the key exists if it does then
- # update the attributes of the object
- # otherwise set a new paginator
- key = data.parent_id
- if $scope.expanders[key]?
- $scope.expanders[key].setAttributes(responseHeaders())
- else
- pageObject = new ZoomedPaginator(responseHeaders())
- $scope.expanders[key] = pageObject
- # Callback for $resource. Takes two parameters
- # data -- the body of the response
- # responseHeaders -- response headers which contain pagination
- # information from the last request
- returnIndexResponseHeaders = (data, responseHeaders) ->
- setExpanderPaginationObj(data, responseHeaders)
- returnShowResponseHeaders = (data, responseHeaders) ->
- setZoomedExpanderPaginationObj(data, responseHeaders)
- # If there is no course there isn't any reason
- # to go further
- if gon_object.course
- defaultParams =
- course_id: gon_object.course.id
- chapter_id: gon.chapter_id
- # Loads the comment that all other comments hang off of
- # you don't see this one but you need it.
- loadBaseComment = () ->
- params = _.extend({}, defaultParams, { parent_id: null })
- CourseCommentV2.list([], params, false, returnIndexResponseHeaders)
- .then((response) ->
- _.extend($scope.courseComment, response[0])
- [$scope.courseComment]
- )
- # id - of comment
- # viewable - bool - if false then then toggles the requestState
- # logic to shut forms on and off
- $scope.formRequested = (id, viewable) ->
- viewable = viewable || true
- $scope.forms[id] = viewable
- $scope.$on('openReplyForm', (event, comment) ->
- $scope.formRequested(comment.id)
- )
- # loads all comments besides the base comments
- # pass in the comment that you want to start with
- # for example on page load you should start with the base comment
- # and this will grab all the latest(TODO server side - criteria you pass in) N comments
- # from that comment down
- # options
- # per_page: int -- number of comments per page
- # page: int -- page number that you would like the comments returned from
- #
- loadChildComments = (comments, options) ->
- options = options || {}
- if comments? && comments.length > 0
- angular.forEach(comments, (comment) ->
- if comment.level? && comment.level is MAX_COMMENT_LEVEL
- setCommentStateToReady()
- return comment
- else
- incrementRequestsWaiting()
- addChildrenContainer(comment)
- params = _.extend({}, defaultParams, { parent_id: comment.id }, options)
- CourseCommentV2.list([], params, false, returnIndexResponseHeaders)
- .then((res) ->
- # have to reverse to display correctly
- res.reverse() unless (comment.level is 1 && $scope.sortOrder is $scope.STATES.MOST_POPULAR) || (options.reverse is false)
- if options.stackingOrder is 'bottom'
- Array.prototype.unshift.apply(comment.children, res)
- else
- Array.prototype.push.apply(comment.children, res)
- decrementRequestsWaiting()
- loadChildComments(res)
- )
- )
- else
- setCommentStateToReady()
- return
- # API for expander bar
- # this should really just take an options hash
- # the expander should know what to do with the comment
- $scope.loadMore = (comment, paginationOptions) ->
- $scope.deferred = $q.defer()
- loadChildComments(comment, paginationOptions)
- $scope.deferred.promise
- loadComments = (paginationOptions, respectQueryParams) ->
- # make a top level promise
- # that will get fulfilled once all the comments
- # have been retrieved
- $scope.deferred = $q.defer()
- if gon.comment_id? && respectQueryParams isnt false
- $scope.sortOrder = $scope.STATES.ZOOMED
- loadZoomedComments(gon.comment_id, returnShowResponseHeaders)
- .then((response) ->
- targetComment = findNode(gon.comment_id, $scope.courseComment)
- loadChildComments([targetComment])
- response
- )
- else
- loadBaseComment()
- .then((response) ->
- params = _.extend({}, paginationOptions, { reverse: false })
- loadChildComments(response, params)
- )
- $scope.deferred.promise
- $scope.loadCommentsOfType = (type) ->
- if type is $scope.STATES.CHRONOLOGICAL
- loadChronologicalComments()
- else if type is $scope.STATES.MOST_POPULAR
- $scope.loadPopularComments()
- $scope.loadPopularComments = () ->
- $scope.sortOrder = $scope.STATES.MOST_POPULAR
- clearObject($scope.expanders)
- clearObject($scope.forms)
- delete $scope.courseComment.children
- options =
- sort_by_type: 'most_popular'
- loadChildComments([$scope.courseComment], options)
- loadChronologicalComments = () ->
- $scope.sortOrder = $scope.STATES.CHRONOLOGICAL
- clearObject($scope.expanders)
- clearObject($scope.forms)
- $scope.courseComment.children.splice(0) if $scope.courseComment.children
- paginationOptions =
- page: DEFAULT_PAGE
- per_page: DEFAULT_PER_PAGE
- loadComments(paginationOptions, false)
- .then((response) ->
- $scope.ready = true
- )
- clearObject = (object) ->
- for prop of object
- delete object[prop]
- # recurse up the comments parent_id until
- # there is no parent_id and builds the $scope.courseComment
- # by swapping the last for the latest and making the last children
- # of the latest
- # pass the callback as the second parameter to get the response
- # headers
- loadZoomedComments = (id, cb) ->
- if id?
- # example hash
- # { _id: 2913, nameSpace: 'course_comment' }
- CourseCommentV2.get({ _id: id , nameSpace: 'course_comment'}, cb)
- .then((response) ->
- destination = {}
- angular.copy($scope.courseComment, destination)
- $scope.courseComment = response
- $scope.courseComment.children = []
- # If there are keys which means that this isn't the first
- # recurse then add the destination as the child
- if Object.keys(destination).length > 0
- $scope.courseComment.children.push(destination)
- loadZoomedComments(response.parent_id, cb)
- )
- else
- return
- # recursively find all nodes that match attr1 == val1
- # sets attr2 to val2
- # used for updating user profile photo in courseComments
- $scope.updateNode = (attr1, val1, attr2, val2, currentNode) ->
- if currentNode[attr1] == val1
- currentNode[attr2] = val2
- # only do this if there are children
- if currentNode.children
- i = 0
- while i < currentNode.children.length
- currentChild = currentNode.children[i]
- # search in the current child
- $scope.updateNode(attr1, val1, attr2, val2, currentChild)
- i += 1
- updateStudentDetails = () ->
- $('body').on('profileReady', (event, updated, object) ->
- $scope.updateNode('user_id', object.user.id, 'student_details', buildStudentDetails(object), $scope.courseComment)
- $scope.updateNode('user_id', object.user.id, 'user_name', buildUserName(object), $scope.courseComment)
- $scope.$apply()
- )
- buildStudentDetails = (object) ->
- if object.mini_bio != "" and object.location != ""
- ''.concat(object.mini_bio, ', ', object.location)
- else if object.mini_bio != ""
- ''.concat(object.mini_bio)
- else if object.location != ""
- ''.concat(object.location)
- buildUserName = (object) ->
- ''.concat(object.first_name, ' ', object.last_name)
- watchUserAvatar = () ->
- $scope.$watch('currentUser.profile_photo_url', (newValue, oldValue) ->
- if newValue != oldValue
- loadUserAvatar(newValue)
- )
- loadUserAvatar = (photo_url) ->
- img = new Image()
- if photo_url?
- $scope.updateNode('user_id', $scope.currentUser.id, 'user_profile_photo_url', photo_url, $scope.courseComment)
- img.onload = () ->
- $timeout ->
- $scope.userAvatarLoaded = true
- $scope.userAvatarFailed = false
- $scope.$apply()
- , 0, false
- img.onerror = () ->
- $timeout ->
- $scope.userAvatarFailed = true
- $scope.userAvatarLoaded = false
- $scope.$apply()
- , 0, false
- img.src = $scope.currentUser.profile_photo_url
- # All methods that are executed on initialization of the controller
- # should be in an init method
- init = () ->
- paginationOptions =
- page: DEFAULT_PAGE
- per_page: DEFAULT_PER_PAGE
- loadComments(paginationOptions)
- .then((response) ->
- loadUserAvatar()
- watchUserAvatar()
- updateStudentDetails()
- $scope.ready = true
- )
- init()
- ])
Add Comment
Please, Sign In to add comment