diff --git a/services/web/app/views/templates.jade b/services/web/app/views/templates.jade index 1971a6c8c2..00d18cdb20 100644 --- a/services/web/app/views/templates.jade +++ b/services/web/app/views/templates.jade @@ -22,7 +22,7 @@ script(type="text/template")#tabTemplate li(id="{{ id }}-tab-li") - a(href="#", data-toggle="tab", data-target="\\#{{ id }}-tab", class="tab-link {{ id }}-tab") + a(href="#", data-toggle="tab", data-target="\\#{{ show }}-tab", class="tab-link {{ id }}-tab") .content {{ name }} script(type="text/template")#tabContentTemplate @@ -436,6 +436,12 @@ .change-list-area .track-changes-diff + script(type='text/template')#trackChangesDiffTemplate + .track-changes-diff-toolbar.btn-toolbar + .number-of-changes {{ changes }} in {{ name }} + a(href="#").restore.btn.btn-small.btn-danger Restore to before these changes + .track-changes-diff-editor + script(type='text/template')#changeListItemTemplate div(class='change-selectors') div.range @@ -447,9 +453,6 @@ div.change-date {{date}} div {{{users}}} - div(class='restore') - a(href="#") Restore to here - script(type='text/template')#changeListItemUserTemplate div(class='change-name') div.color-square(style="background-color: hsl({{hue}}, 100%, 70%);") diff --git a/services/web/public/coffee/file-tree/FileTreeManager.coffee b/services/web/public/coffee/file-tree/FileTreeManager.coffee index f78629f388..81d40687a9 100644 --- a/services/web/public/coffee/file-tree/FileTreeManager.coffee +++ b/services/web/public/coffee/file-tree/FileTreeManager.coffee @@ -97,7 +97,7 @@ define [ @views[@selected_entity_id].deselect() @selected_entity_id = entity_id @ide.sideBarView.deselectAll() - @views[entity_id].select() + @views[entity_id]?.select() getEntity: (entity_id) -> @views[entity_id]?.model diff --git a/services/web/public/coffee/ide/TabManager.coffee b/services/web/public/coffee/ide/TabManager.coffee index bd82376a38..e4c1b3ca70 100644 --- a/services/web/public/coffee/ide/TabManager.coffee +++ b/services/web/public/coffee/ide/TabManager.coffee @@ -17,8 +17,9 @@ define [ addTab: (options) -> @tabs.push options + options.show ||= options.id tabEl = $(Mustache.to_html @templates.tab, options) - tabEl.find("a").attr("href", "#" + options.id) + tabEl.find("a").attr("href", "#" + options.show) if options.content? contentEl = $(Mustache.to_html @templates.content, options) @@ -53,6 +54,8 @@ define [ if options.contract @contract() + show: (tab) -> + $("##{tab}-tab-li > a").tab("show") lockOpen: () -> @locked_open = true diff --git a/services/web/public/coffee/track-changes/ChangeListView.coffee b/services/web/public/coffee/track-changes/ChangeListView.coffee index 348b5fbe9b..afa2714d7e 100644 --- a/services/web/public/coffee/track-changes/ChangeListView.coffee +++ b/services/web/public/coffee/track-changes/ChangeListView.coffee @@ -75,9 +75,6 @@ define [ delete @hoverFromIndex @resetHoverStates() - view.on "click:restore", (e) => - @trigger "restore", view.model - view.resetSelector(index, @selectedFromIndex, @selectedToIndex) setSelectionRange: (fromIndex, toIndex) -> @@ -173,8 +170,6 @@ define [ @trigger "mouseenter:from", args... "mouseleave .change-selector-from": (args...) -> @trigger "mouseleave:from", args... - "click .restore a": "onRestoreClick" - templates: item: $("#changeListItemTemplate").html() @@ -214,10 +209,6 @@ define [ onFromSelectorClick: (e) -> @trigger "selected:from", e, @ - onRestoreClick: (e) -> - e.preventDefault() - @trigger "click:restore", e, @ - isSelectedFrom: () -> @$(".change-selector-from").is(":checked") diff --git a/services/web/public/coffee/track-changes/DiffView.coffee b/services/web/public/coffee/track-changes/DiffView.coffee index 174e7547ee..0ac6002e8c 100644 --- a/services/web/public/coffee/track-changes/DiffView.coffee +++ b/services/web/public/coffee/track-changes/DiffView.coffee @@ -4,15 +4,33 @@ define [ "ace/range" "moment" "libs/backbone" + "libs/mustache" ], (Ace, LatexMode, Range, moment)-> DiffView = Backbone.View.extend + template: $("#trackChangesDiffTemplate").html() + + events: + "click .restore": () -> + console.log "click" + @trigger "restore" + initialize: () -> @model.on "change:diff", () => @render() - @render() render: -> diff = @model.get("diff") return unless diff? + + changes = @getNumberOfChanges() + html = Mustache.to_html @template, { + changes: "#{changes} change#{if changes == 1 then "" else "s"}" + name: @model.get("doc")?.get("name") + } + @$el.html(html) + + if !@model.get("from")? or !@model.get("to")? or changes == 0 + @$(".restore").hide() + @createAceEditor() @aceEditor.setValue(@getPlainDiffContent()) @aceEditor.clearSelection() @@ -24,12 +42,12 @@ define [ @scrollToFirstChange() return @ - destroy: () -> + remove: () -> @$editor?.remove() + @undelegateEvents() createAceEditor: () -> - @$el.empty() - @$editor = $("
") + @$editor = @$(".track-changes-diff-editor") @$el.append(@$editor) @aceEditor = Ace.edit(@$editor[0]) @aceEditor.setTheme("ace/theme/#{window.userSettings.theme}") @@ -54,6 +72,12 @@ define [ content += entry.u or entry.i or entry.d or "" return content + getNumberOfChanges: () -> + changes = 0 + for entry in @model.get("diff") or [] + changes += 1 if entry.i? or entry.d? + return changes + insertMarkers: () -> row = 0 column = 0 diff --git a/services/web/public/coffee/track-changes/TrackChangesManager.coffee b/services/web/public/coffee/track-changes/TrackChangesManager.coffee index 52a4f2a4fa..ab27d883a1 100644 --- a/services/web/public/coffee/track-changes/TrackChangesManager.coffee +++ b/services/web/public/coffee/track-changes/TrackChangesManager.coffee @@ -20,6 +20,7 @@ define [ @ide.tabManager.addTab id: "history" name: "History" + show: "code" after: "code" contract: true onShown: () => @show() @@ -56,11 +57,8 @@ define [ @changeListView.on "change_diff", (fromIndex, toIndex) => @selectDocAndUpdateDiff(fromIndex, toIndex) - @changeListView.on "restore", (change) => - @restore(change) - if @diffView? - @diffView.destroy() + @diffView.remove() @ide.mainAreaManager.change "trackChanges" @ide.editor.disable() @@ -72,7 +70,7 @@ define [ @ide.fileViewManager.enable() @disable() @ide.fileTreeManager.openDoc(@doc_id) - @ide.mainAreaManager.change "editor" + @ide.tabManager.show "code" autoSelectDiff: () -> if @changes.models.length == 0 @@ -113,33 +111,41 @@ define [ console.log "No selection - what should we do!?" return - {from, to} = @_findDocVersionsRangeInSelection(@doc_id, fromIndex, toIndex) - - if !from? or !to? - console.log "No diff, should probably just show latest version" - return + {from, to, start_ts, end_ts} = @_findDocVersionsRangeInSelection(@doc_id, fromIndex, toIndex) @diff = new Diff({ project_id: @project_id doc_id: @doc_id from: from - to: to + to: to + start_ts: start_ts + end_ts: end_ts + }, { + ide: @ide }) if @diffView? - @diffView.destroy() + @diffView.remove() + + if !@diff.get("doc")? + console.log "This document has been deleted. What should we do?" + return + @diffView = new DiffView( model: @diff el: @$el.find(".track-changes-diff") ) + + @diffView.on "restore", () => + @restoreDiff(@diff) + @diff.fetch() @ide.fileTreeManager.selectEntity(@doc_id) _findDocVersionsRangeInSelection: (doc_id, fromIndex, toIndex) -> - from = null - to = null + from = to = start_ts = end_ts = null for change in @changes.models.slice(toIndex, fromIndex + 1) for doc in change.get("docs") @@ -147,16 +153,20 @@ define [ if from? and to? from = Math.min(from, doc.fromV) to = Math.max(to, doc.toV) + start_ts = Math.min(start_ts, change.get("start_ts")) + end_ts = Math.max(end_ts, change.get("end_ts")) else from = doc.fromV to = doc.toV + start_ts = change.get("start_ts") + end_ts = change.get("end_ts") break - return {from, to} + return {from, to, start_ts, end_ts} - restore: (change) -> - name = @ide.fileTreeManager.getNameOfEntityId(@doc_id) - date = moment(change.get("start_ts")).format("Do MMM YYYY, h:mm:ss a") + restoreDiff: (diff) -> + name = diff.get("doc")?.get("name") + date = moment(diff.get("start_ts")).format("Do MMM YYYY, h:mm:ss a") modal = new Modal({ title: "Restore document" message: "Are you sure you want to restore #{name} to before the changes on #{date}?" @@ -169,24 +179,12 @@ define [ callback: ($button) => $button.text("Restoring...") $button.prop("disabled", true) - @doRestore change.get("version"), (error) => + diff.restore (error) => modal.remove() @hide() }] }) - doRestore: (version, callback = (error) ->) -> - $.ajax { - url: "/project/#{@project_id}/doc/#{@doc_id}/version/#{version}/restore" - type: "POST" - headers: - "X-CSRF-Token": window.csrfToken - success: () -> - callback() - error: (error) -> - callback(error) - } - enable: () -> @enabled = true diff --git a/services/web/public/coffee/track-changes/models/Diff.coffee b/services/web/public/coffee/track-changes/models/Diff.coffee index 52ad05c439..d8ee48726f 100644 --- a/services/web/public/coffee/track-changes/models/Diff.coffee +++ b/services/web/public/coffee/track-changes/models/Diff.coffee @@ -3,8 +3,15 @@ define [ "libs/backbone" ], (User) -> Diff = Backbone.Model.extend + initialize: (attributes, options) -> + @ide = options.ide + @set "doc", @ide.fileTreeManager.getEntity(@get("doc_id")) + url: () -> - "/project/#{@get("project_id")}/doc/#{@get("doc_id")}/diff?from=#{@get("from")}&to=#{@get("to")}" + url = "/project/#{@get("project_id")}/doc/#{@get("doc_id")}/diff" + if @get("from")? and @get("to")? + url += "?from=#{@get("from")}&to=#{@get("to")}" + return url parse: (diff) -> for entry in diff.diff @@ -14,3 +21,15 @@ define [ else entry.meta.user = User.getAnonymousUser() return diff + + restore: (callback = (error) ->) -> + $.ajax { + url: "/project/#{@get("project_id")}/doc/#{@get("doc_id")}/version/#{@get("from")}/restore" + type: "POST" + headers: + "X-CSRF-Token": window.csrfToken + success: () -> + callback() + error: (error) -> + callback(error) + } diff --git a/services/web/public/stylesheets/less/trackchanges.less b/services/web/public/stylesheets/less/trackchanges.less index a7d0455f2c..82f668d9ad 100644 --- a/services/web/public/stylesheets/less/trackchanges.less +++ b/services/web/public/stylesheets/less/trackchanges.less @@ -8,11 +8,10 @@ left: 0; top: 0; bottom: 0; - padding: 0px 12px; height: 100%; .ace_editor { position: absolute; - top: 0; + top: 30px; left: 0; right: 0; bottom: 0; @@ -20,6 +19,30 @@ display: none; } } + .track-changes-diff-toolbar { + position: absolute; + top: 0; + left: 0; + right: -1px; + height: 20px; + padding: 5px 5px 5px 5px; + margin: 0; + background-color: #282828; + color: white; + border-right: 1px solid white; + .number-of-changes, .restore { + position: absolute; + } + .number-of-changes { + left: 10px; + bottom: 7px; + } + .restore { + right: 10px; + bottom: 5px; + padding: 3px 9px; + } + } } .track-changes-side-bar { @@ -181,11 +204,10 @@ li.selected-change-from { .change-selectors { .range { - bottom: 37px; + bottom: 10px; } .change-selector-from { opacity: 1; - bottom: 32px; } } .restore { @@ -230,12 +252,5 @@ } } } - li.selected-change-from.hover-selected-from { - .change-selectors { - .range { - bottom: 37px; - } - } - } } } \ No newline at end of file