Guest User

Untitled

a guest
May 27th, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.56 KB | None | 0 0
  1. angular
  2. .module('CourseCommentV2')
  3. .controller('CourseCommentsV2Ctrl', [
  4. '$scope', 'gon_object', 'CourseCommentV2', '$q', '$timeout', 'Paginator', 'ZoomedPaginator',
  5. ($scope, gon_object, CourseCommentV2, $q, $timeout, Paginator, ZoomedPaginator) ->
  6.  
  7. # Don't think this should be configurable
  8. # since this would be a huge change.
  9. MAX_COMMENT_LEVEL = 3
  10. THREAD_LEVEL = 2
  11. REPLY_LEVEL = 3
  12.  
  13. # We might want this configurable but not
  14. # likely to change super often
  15. DEFAULT_PER_PAGE = 5
  16. DEFAULT_PAGE = 1
  17.  
  18. $scope.STATES =
  19. CHRONOLOGICAL: 0
  20. MOST_POPULAR: 1
  21. ZOOMED: 2
  22.  
  23. $scope.currentUser = gon_object.user
  24.  
  25. # make the baseComment available immmediately and
  26. # merge onto it
  27. $scope.courseComment = {}
  28. $scope.expanders = {}
  29. $scope.forms = {}
  30. $scope.sortOrder = $scope.STATES.CHRONOLOGICAL
  31.  
  32. # Keep track of asynchronous calls
  33. $scope.requestsWaiting = 0
  34.  
  35. # Make sure anything relying on the nested structure isn't
  36. # called until the data structure is ready
  37. $scope.ready = false
  38.  
  39. $scope.hasMoreComments = (id, displayState) ->
  40. ($scope.expanders[id] and $scope.expanders[id].isLastPage() is false) and $scope.sortState is displayState
  41.  
  42. # This removes the comment from the within the
  43. # parent scope.courseComment object which contains
  44. # all the comments and replies that are rendered
  45. $scope.deleteComment = (id, parent_id) ->
  46. idx = undefined
  47. parentNode = findNode(parent_id, $scope.courseComment)
  48. if parentNode?
  49. for child, index in parentNode.children
  50. if child.id is id
  51. idx = index
  52. parentNode.children.splice(idx, 1) if idx?
  53.  
  54. # Recursive find for deleting or doing something to the
  55. # nested children of scope.courseComment
  56. findNode = (id, currentNode) ->
  57. i = undefined
  58. currentChild = undefined
  59. result = undefined
  60. if id == currentNode.id
  61. currentNode
  62. else
  63. if currentNode.children?
  64. i = 0
  65. while i < currentNode.children.length
  66. currentChild = currentNode.children[i]
  67. # Search in the current child
  68. result = findNode(id, currentChild)
  69. # Return the result if the node has been found
  70. if result != false
  71. return result
  72. i += 1
  73. # The node has not been found and we have no more options
  74. false
  75.  
  76. # Use timeout to guarantee the check of
  77. # requestsWaiting waits until the next event loop
  78. setCommentStateToReady = () ->
  79. $timeout ->
  80. if $scope.requestsWaiting is 0
  81. $scope.deferred.resolve($scope.courseComment)
  82. , 0, false
  83.  
  84. incrementRequestsWaiting = () ->
  85. $scope.requestsWaiting++
  86.  
  87. decrementRequestsWaiting = () ->
  88. --$scope.requestsWaiting
  89.  
  90. addChildrenContainer = (comment) ->
  91. comment.children = [] unless comment.children?
  92.  
  93. setExpanderPaginationObj = (data, responseHeaders) ->
  94. # check if there are children and if there are grab
  95. # if the level is 2 or greater it means that it is not the base
  96. # comment
  97. if data[0]? and data[0].level >= 2
  98. key = data[0].parent_id
  99. # TODO check if the key exists if it does then
  100. # update the attributes of the object
  101. # otherwise set a new paginator
  102. if $scope.expanders[key]?
  103. $scope.expanders[key].setAttributes(responseHeaders())
  104. else
  105. pageObject = new Paginator(responseHeaders())
  106. $scope.expanders[key] = pageObject
  107.  
  108. setZoomedExpanderPaginationObj = (data, responseHeaders) ->
  109. if data? and data.course_comment? && data.course_comment.level >= 2
  110. data = data.course_comment
  111. # TODO check if the key exists if it does then
  112. # update the attributes of the object
  113. # otherwise set a new paginator
  114. key = data.parent_id
  115. if $scope.expanders[key]?
  116. $scope.expanders[key].setAttributes(responseHeaders())
  117. else
  118. pageObject = new ZoomedPaginator(responseHeaders())
  119. $scope.expanders[key] = pageObject
  120.  
  121. # Callback for $resource. Takes two parameters
  122. # data -- the body of the response
  123. # responseHeaders -- response headers which contain pagination
  124. # information from the last request
  125. returnIndexResponseHeaders = (data, responseHeaders) ->
  126. setExpanderPaginationObj(data, responseHeaders)
  127.  
  128. returnShowResponseHeaders = (data, responseHeaders) ->
  129. setZoomedExpanderPaginationObj(data, responseHeaders)
  130.  
  131. # If there is no course there isn't any reason
  132. # to go further
  133. if gon_object.course
  134. defaultParams =
  135. course_id: gon_object.course.id
  136. chapter_id: gon.chapter_id
  137.  
  138. # Loads the comment that all other comments hang off of
  139. # you don't see this one but you need it.
  140. loadBaseComment = () ->
  141. params = _.extend({}, defaultParams, { parent_id: null })
  142. CourseCommentV2.list([], params, false, returnIndexResponseHeaders)
  143. .then((response) ->
  144. _.extend($scope.courseComment, response[0])
  145. [$scope.courseComment]
  146. )
  147.  
  148. # id - of comment
  149. # viewable - bool - if false then then toggles the requestState
  150. # logic to shut forms on and off
  151. $scope.formRequested = (id, viewable) ->
  152. viewable = viewable || true
  153. $scope.forms[id] = viewable
  154.  
  155. $scope.$on('openReplyForm', (event, comment) ->
  156. $scope.formRequested(comment.id)
  157. )
  158.  
  159. # loads all comments besides the base comments
  160. # pass in the comment that you want to start with
  161. # for example on page load you should start with the base comment
  162. # and this will grab all the latest(TODO server side - criteria you pass in) N comments
  163. # from that comment down
  164. # options
  165. # per_page: int -- number of comments per page
  166. # page: int -- page number that you would like the comments returned from
  167. #
  168.  
  169. loadChildComments = (comments, options) ->
  170. options = options || {}
  171. if comments? && comments.length > 0
  172. angular.forEach(comments, (comment) ->
  173. if comment.level? && comment.level is MAX_COMMENT_LEVEL
  174. setCommentStateToReady()
  175. return comment
  176. else
  177. incrementRequestsWaiting()
  178. addChildrenContainer(comment)
  179. params = _.extend({}, defaultParams, { parent_id: comment.id }, options)
  180. CourseCommentV2.list([], params, false, returnIndexResponseHeaders)
  181. .then((res) ->
  182. # have to reverse to display correctly
  183. res.reverse() unless (comment.level is 1 && $scope.sortOrder is $scope.STATES.MOST_POPULAR) || (options.reverse is false)
  184. if options.stackingOrder is 'bottom'
  185. Array.prototype.unshift.apply(comment.children, res)
  186. else
  187. Array.prototype.push.apply(comment.children, res)
  188. decrementRequestsWaiting()
  189. loadChildComments(res)
  190. )
  191. )
  192. else
  193. setCommentStateToReady()
  194. return
  195.  
  196. # API for expander bar
  197. # this should really just take an options hash
  198. # the expander should know what to do with the comment
  199. $scope.loadMore = (comment, paginationOptions) ->
  200. $scope.deferred = $q.defer()
  201. loadChildComments(comment, paginationOptions)
  202. $scope.deferred.promise
  203.  
  204. loadComments = (paginationOptions, respectQueryParams) ->
  205. # make a top level promise
  206. # that will get fulfilled once all the comments
  207. # have been retrieved
  208. $scope.deferred = $q.defer()
  209. if gon.comment_id? && respectQueryParams isnt false
  210. $scope.sortOrder = $scope.STATES.ZOOMED
  211. loadZoomedComments(gon.comment_id, returnShowResponseHeaders)
  212. .then((response) ->
  213. targetComment = findNode(gon.comment_id, $scope.courseComment)
  214. loadChildComments([targetComment])
  215. response
  216. )
  217. else
  218. loadBaseComment()
  219. .then((response) ->
  220. params = _.extend({}, paginationOptions, { reverse: false })
  221. loadChildComments(response, params)
  222. )
  223. $scope.deferred.promise
  224.  
  225. $scope.loadCommentsOfType = (type) ->
  226. if type is $scope.STATES.CHRONOLOGICAL
  227. loadChronologicalComments()
  228. else if type is $scope.STATES.MOST_POPULAR
  229. $scope.loadPopularComments()
  230.  
  231. $scope.loadPopularComments = () ->
  232. $scope.sortOrder = $scope.STATES.MOST_POPULAR
  233. clearObject($scope.expanders)
  234. clearObject($scope.forms)
  235. delete $scope.courseComment.children
  236. options =
  237. sort_by_type: 'most_popular'
  238. loadChildComments([$scope.courseComment], options)
  239.  
  240. loadChronologicalComments = () ->
  241. $scope.sortOrder = $scope.STATES.CHRONOLOGICAL
  242. clearObject($scope.expanders)
  243. clearObject($scope.forms)
  244. $scope.courseComment.children.splice(0) if $scope.courseComment.children
  245. paginationOptions =
  246. page: DEFAULT_PAGE
  247. per_page: DEFAULT_PER_PAGE
  248. loadComments(paginationOptions, false)
  249. .then((response) ->
  250. $scope.ready = true
  251. )
  252.  
  253. clearObject = (object) ->
  254. for prop of object
  255. delete object[prop]
  256.  
  257. # recurse up the comments parent_id until
  258. # there is no parent_id and builds the $scope.courseComment
  259. # by swapping the last for the latest and making the last children
  260. # of the latest
  261. # pass the callback as the second parameter to get the response
  262. # headers
  263. loadZoomedComments = (id, cb) ->
  264. if id?
  265. # example hash
  266. # { _id: 2913, nameSpace: 'course_comment' }
  267. CourseCommentV2.get({ _id: id , nameSpace: 'course_comment'}, cb)
  268. .then((response) ->
  269. destination = {}
  270. angular.copy($scope.courseComment, destination)
  271. $scope.courseComment = response
  272. $scope.courseComment.children = []
  273. # If there are keys which means that this isn't the first
  274. # recurse then add the destination as the child
  275. if Object.keys(destination).length > 0
  276. $scope.courseComment.children.push(destination)
  277. loadZoomedComments(response.parent_id, cb)
  278. )
  279. else
  280. return
  281.  
  282.  
  283. # recursively find all nodes that match attr1 == val1
  284. # sets attr2 to val2
  285. # used for updating user profile photo in courseComments
  286. $scope.updateNode = (attr1, val1, attr2, val2, currentNode) ->
  287. if currentNode[attr1] == val1
  288. currentNode[attr2] = val2
  289. # only do this if there are children
  290. if currentNode.children
  291. i = 0
  292. while i < currentNode.children.length
  293. currentChild = currentNode.children[i]
  294. # search in the current child
  295. $scope.updateNode(attr1, val1, attr2, val2, currentChild)
  296. i += 1
  297.  
  298. updateStudentDetails = () ->
  299. $('body').on('profileReady', (event, updated, object) ->
  300. $scope.updateNode('user_id', object.user.id, 'student_details', buildStudentDetails(object), $scope.courseComment)
  301. $scope.updateNode('user_id', object.user.id, 'user_name', buildUserName(object), $scope.courseComment)
  302. $scope.$apply()
  303. )
  304.  
  305. buildStudentDetails = (object) ->
  306. if object.mini_bio != "" and object.location != ""
  307. ''.concat(object.mini_bio, ', ', object.location)
  308. else if object.mini_bio != ""
  309. ''.concat(object.mini_bio)
  310. else if object.location != ""
  311. ''.concat(object.location)
  312.  
  313. buildUserName = (object) ->
  314. ''.concat(object.first_name, ' ', object.last_name)
  315.  
  316. watchUserAvatar = () ->
  317. $scope.$watch('currentUser.profile_photo_url', (newValue, oldValue) ->
  318. if newValue != oldValue
  319. loadUserAvatar(newValue)
  320. )
  321.  
  322. loadUserAvatar = (photo_url) ->
  323. img = new Image()
  324. if photo_url?
  325. $scope.updateNode('user_id', $scope.currentUser.id, 'user_profile_photo_url', photo_url, $scope.courseComment)
  326.  
  327. img.onload = () ->
  328. $timeout ->
  329. $scope.userAvatarLoaded = true
  330. $scope.userAvatarFailed = false
  331. $scope.$apply()
  332. , 0, false
  333.  
  334. img.onerror = () ->
  335. $timeout ->
  336. $scope.userAvatarFailed = true
  337. $scope.userAvatarLoaded = false
  338. $scope.$apply()
  339. , 0, false
  340.  
  341.  
  342. img.src = $scope.currentUser.profile_photo_url
  343.  
  344.  
  345.  
  346.  
  347. # All methods that are executed on initialization of the controller
  348. # should be in an init method
  349. init = () ->
  350. paginationOptions =
  351. page: DEFAULT_PAGE
  352. per_page: DEFAULT_PER_PAGE
  353. loadComments(paginationOptions)
  354. .then((response) ->
  355. loadUserAvatar()
  356. watchUserAvatar()
  357. updateStudentDetails()
  358. $scope.ready = true
  359. )
  360.  
  361. init()
  362. ])
Add Comment
Please, Sign In to add comment