TrackChangesManager.coffee 4.6 KB

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