TrackChangesManager.coffee 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. define [
  2. "track-changes/models/ChangeList"
  3. "track-changes/models/Diff"
  4. "track-changes/ChangeListView"
  5. "track-changes/DiffView"
  6. "account/AccountManager"
  7. "utils/Modal"
  8. "models/Doc"
  9. "moment"
  10. ], (ChangeList, Diff, ChangeListView, DiffView, AccountManager, Modal, Doc, moment) ->
  11. class TrackChangesManager
  12. template: $("#trackChangesPanelTemplate").html()
  13. constructor: (@ide) ->
  14. @project_id = window.userSettings.project_id
  15. @$el = $(@template)
  16. @ide.mainAreaManager.addArea
  17. identifier: "trackChanges"
  18. element: @$el
  19. @ide.tabManager.addTab
  20. id: "history"
  21. name: "History"
  22. show: "code"
  23. after: "code"
  24. contract: true
  25. onShown: () => @show()
  26. onHidden: () => @hide()
  27. @ide.editor.on "resize", () =>
  28. @diffView?.resize()
  29. @$el.find(".track-changes-close").on "click", (e) =>
  30. e.preventDefault
  31. @hide()
  32. @bindToFileTreeEvents()
  33. @disable()
  34. bindToFileTreeEvents: () ->
  35. @ide.fileTreeManager.on "open:doc", (doc_id) =>
  36. @doc_id = doc_id
  37. if @enabled
  38. @updateDiff()
  39. AB_BUCKETS: ["control", "one-week", "pop-up"]
  40. show: () ->
  41. @changes = new ChangeList([], project_id: @project_id, ide: @ide)
  42. if @changeListView?
  43. @changeListView.remove()
  44. @changeListView = new ChangeListView(
  45. el: @$el.find(".change-list-area")
  46. collection: @changes
  47. )
  48. @changeListView.render()
  49. @changeListView.loadUntilFull (error) =>
  50. @autoSelectDiff()
  51. @changeListView.on "change_diff", (fromIndex, toIndex) =>
  52. @findDocsInChange(fromIndex, toIndex)
  53. @updateLabels()
  54. @updateDiff()
  55. @showUpgradeView()
  56. if @diffView?
  57. @diffView.remove()
  58. @ide.mainAreaManager.change "trackChanges"
  59. @ide.editor.disable()
  60. @ide.fileViewManager.disable()
  61. @enable()
  62. showUpgradeView: () ->
  63. @$el.find("button.start-free-trial").off "click.track-changes"
  64. @$el.find("button.start-free-trial").on "click.track-changes", () => @gotoFreeTrial()
  65. if !@ide.project.get("features").versioning
  66. ga('send', 'event', 'subscription-funnel', 'askToUgrade', "trackchanges")
  67. @$el.find(".track-changes-upgrade-popup").show()
  68. if @ide.project.get("owner") == @ide.user
  69. @$el.find(".show-when-not-owner").hide()
  70. else
  71. @$el.find(".show-when-owner").hide()
  72. hide: () ->
  73. @ide.editor.enable()
  74. @ide.fileViewManager.enable()
  75. @disable()
  76. @ide.fileTreeManager.openDoc(@doc_id)
  77. @ide.tabManager.show "code"
  78. @resetLabels()
  79. autoSelectDiff: () ->
  80. if @changes.models.length == 0
  81. return
  82. # Find all change until the last one we made
  83. fromIndex = null
  84. for change, i in @changes.models
  85. if ide.user in change.get("users")
  86. if i > 0
  87. fromIndex = i - 1
  88. else
  89. fromIndex = 0
  90. break
  91. fromIndex = 0 if !fromIndex
  92. toChange = @changes.models[0]
  93. fromChange = @changes.models[fromIndex]
  94. @changeListView.setSelectionRange(fromIndex, 0)
  95. @updateDiff()
  96. findDocsInChange: (fromIndex, toIndex) ->
  97. @changed_doc_ids = []
  98. for change in @changes.models.slice(toIndex, fromIndex + 1)
  99. for doc in change.get("docs") or []
  100. @changed_doc_ids.push doc.id if doc.id not in @changed_doc_ids
  101. if !@doc_id? or @doc_id not in @changed_doc_ids
  102. @doc_id = @changed_doc_ids[0]
  103. @updateDiff()
  104. updateLabels: () ->
  105. labels = {}
  106. for doc_id in @changed_doc_ids
  107. labels[doc_id] = true
  108. @ide.fileTreeManager.setLabels(labels)
  109. resetLabels: () ->
  110. @ide.fileTreeManager.setLabels({})
  111. updateDiff: () ->
  112. fromIndex = @changeListView.selectedFromIndex
  113. toIndex = @changeListView.selectedToIndex
  114. if !toIndex? or !fromIndex?
  115. console.log "No selection - what should we do!?"
  116. return
  117. {from, to, start_ts, end_ts} = @_findDocVersionsRangeInSelection(@doc_id, fromIndex, toIndex)
  118. @diff = new Diff({
  119. project_id: @project_id
  120. doc_id: @doc_id
  121. from: from
  122. to: to
  123. start_ts: start_ts
  124. end_ts: end_ts
  125. }, {
  126. ide: @ide
  127. })
  128. if @diffView?
  129. @diffView.remove()
  130. if !@diff.get("doc")?
  131. console.log "This document has been deleted. What should we do?"
  132. return
  133. @diffView = new DiffView(
  134. model: @diff
  135. el: @$el.find(".track-changes-diff")
  136. )
  137. @diffView.on "restore", () =>
  138. @restoreDiff(@diff)
  139. @diff.fetch()
  140. @ide.fileTreeManager.selectEntity(@doc_id)
  141. _findDocVersionsRangeInSelection: (doc_id, fromIndex, toIndex) ->
  142. from = to = start_ts = end_ts = null
  143. for change in @changes.models.slice(toIndex, fromIndex + 1)
  144. for doc in change.get("docs")
  145. if doc.id == doc_id
  146. if from? and to?
  147. from = Math.min(from, doc.fromV)
  148. to = Math.max(to, doc.toV)
  149. start_ts = Math.min(start_ts, change.get("start_ts"))
  150. end_ts = Math.max(end_ts, change.get("end_ts"))
  151. else
  152. from = doc.fromV
  153. to = doc.toV
  154. start_ts = change.get("start_ts")
  155. end_ts = change.get("end_ts")
  156. break
  157. return {from, to, start_ts, end_ts}
  158. restoreDiff: (diff) ->
  159. name = diff.get("doc")?.get("name")
  160. date = moment(diff.get("start_ts")).format("Do MMM YYYY, h:mm:ss a")
  161. modal = new Modal({
  162. title: "Restore document"
  163. message: "Are you sure you want to restore <strong>#{name}</strong> to before the changes on #{date}?"
  164. buttons: [{
  165. text: "Cancel"
  166. }, {
  167. text: "Restore"
  168. class: "btn-success"
  169. close: false
  170. callback: ($button) =>
  171. $button.text("Restoring...")
  172. $button.prop("disabled", true)
  173. diff.restore (error) =>
  174. modal.remove()
  175. @hide()
  176. }]
  177. })
  178. enable: () ->
  179. @enabled = true
  180. disable: () ->
  181. @enabled = false
  182. gotoFreeTrial: () ->
  183. AccountManager.gotoSubscriptionsPage()
  184. ga('send', 'event', 'subscription-funnel', 'upgraded-free-trial', "trackchanges")
  185. return TrackChangesManager