Merge pull request #498 from sharelatex/pr-bulk-actions

Bulk actions
This commit is contained in:
Paulo Jorge Reis 2017-05-18 14:40:44 +01:00 committed by GitHub
commit 04585c59be
7 changed files with 185 additions and 16 deletions

View file

@ -123,20 +123,23 @@ module.exports = DocumentUpdaterHandler =
logger.error project_id:project_id, doc_id:doc_id, url: url, "doc updater returned a non-success status code: #{res.statusCode}"
callback new Error("doc updater returned a non-success status code: #{res.statusCode}")
acceptChange: (project_id, doc_id, change_id, callback = (error) ->) ->
timer = new metrics.Timer("accept-change")
url = "#{settings.apis.documentupdater.url}/project/#{project_id}/doc/#{doc_id}/change/#{change_id}/accept"
logger.log {project_id, doc_id, change_id}, "accepting change in document updater"
request.post url, (error, res, body)->
acceptChanges: (project_id, doc_id, change_ids = [], callback = (error) ->) ->
timer = new metrics.Timer("accept-changes")
reqSettings =
url: "#{settings.apis.documentupdater.url}/project/#{project_id}/doc/#{doc_id}/change/accept"
json:
change_ids: change_ids
logger.log {project_id, doc_id }, "accepting #{ change_ids.length } changes"
request.post reqSettings, (error, res, body)->
timer.done()
if error?
logger.error {err:error, project_id, doc_id, change_id}, "error accepting change in doc updater"
logger.error {err:error, project_id, doc_id }, "error accepting #{ change_ids.length } changes in doc updater"
return callback(error)
if res.statusCode >= 200 and res.statusCode < 300
logger.log {project_id, doc_id, change_id}, "accepted change in document updater"
logger.log {project_id, doc_id }, "accepted #{ change_ids.length } changes in document updater"
return callback(null)
else
logger.error {project_id, doc_id, change_id}, "doc updater returned a non-success status code: #{res.statusCode}"
logger.error {project_id, doc_id }, "doc updater returned a non-success status code: #{res.statusCode}"
callback new Error("doc updater returned a non-success status code: #{res.statusCode}")
deleteThread: (project_id, doc_id, thread_id, callback = (error) ->) ->

View file

@ -6,6 +6,22 @@
ng-click="toggleReviewPanel();"
ng-class="{ 'rp-track-changes-indicator-on-dark' : darkTheme }"
) !{translate("track_changes_is_on")}
a.rp-bulk-actions-btn(
href
ng-if="reviewPanel.selectedEntryIds.length > 1"
ng-click="showBulkAcceptDialog();"
)
i.fa.fa-check
| &nbsp;#{translate("accept_all")}
| ({{ reviewPanel.selectedEntryIds.length }})
a.rp-bulk-actions-btn(
href
ng-if="reviewPanel.selectedEntryIds.length > 1"
ng-click="showBulkRejectDialog();"
)
i.fa.fa-times
| &nbsp;#{translate("reject_all")}
| ({{ reviewPanel.selectedEntryIds.length }})
a.rp-add-comment-btn(
href
ng-if="reviewPanel.entries[editor.open_doc_id]['add-comment'] != null"
@ -13,6 +29,7 @@
)
i.fa.fa-comment
| &nbsp;#{translate("add_comment")}
.review-panel-toolbar
resolved-comments-dropdown(
class="rp-flex-block"
@ -82,6 +99,12 @@
on-submit="submitNewComment(content);"
on-cancel="cancelNewComment();"
)
div(ng-if="entry.type === 'bulk-actions'")
bulk-actions-entry(
on-bulk-accept="showBulkAcceptDialog();"
on-bulk-reject="showBulkRejectDialog();"
n-entries="reviewPanel.selectedEntryIds.length"
)
.rp-entry-list(
ng-if="reviewPanel.subView === SubViews.OVERVIEW"
@ -353,6 +376,25 @@ script(type='text/ng-template', id='addCommentEntryTemplate')
i.fa.fa-comment
| &nbsp;#{translate("comment")}
script(type='text/ng-template', id='bulkActionsEntryTemplate')
div(ng-if="nEntries > 1")
.rp-entry-callout.rp-entry-callout-bulk-actions
.rp-entry.rp-entry-bulk-actions
a.rp-bulk-actions-btn(
href
ng-click="bulkReject();"
)
i.fa.fa-times
| &nbsp;#{translate("reject_all")}
| ({{ nEntries }})
a.rp-bulk-actions-btn(
href
ng-click="bulkAccept();"
)
i.fa.fa-check
| &nbsp;#{translate("accept_all")}
| ({{ nEntries }})
script(type='text/ng-template', id='resolvedCommentsDropdownTemplate')
.resolved-comments
.resolved-comments-backdrop(
@ -433,3 +475,24 @@ script(type="text/ng-template", id="trackChangesUpgradeModalTemplate")
ng-click="cancel()"
)
span #{translate("close")}
script(type="text/ng-template", id="bulkActionsModalTemplate")
.modal-header
button.close(
type="button"
data-dismiss="modal"
ng-click="cancel()"
) &times;
h3 {{ isAccept ? '#{translate("accept_all")}' : '#{translate("reject_all")}' }}
.modal-body
p(ng-if="isAccept") #{translate("bulk_accept_confirm", { nChanges: "{{ nChanges }}"})}
p(ng-if="!isAccept") #{translate("bulk_reject_confirm", { nChanges: "{{ nChanges }}"})}
.modal-footer()
button.btn.btn-default(
ng-click="cancel()"
)
span #{translate("cancel")}
button.btn.btn-primary(
ng-click="confirm()"
)
span #{translate("ok")}

View file

@ -1,11 +1,13 @@
define [
"ide/review-panel/controllers/ReviewPanelController"
"ide/review-panel/controllers/TrackChangesUpgradeModalController"
"ide/review-panel/controllers/BulkActionsModalController"
"ide/review-panel/directives/reviewPanelSorted"
"ide/review-panel/directives/reviewPanelToggle"
"ide/review-panel/directives/changeEntry"
"ide/review-panel/directives/commentEntry"
"ide/review-panel/directives/addCommentEntry"
"ide/review-panel/directives/bulkActionsEntry"
"ide/review-panel/directives/resolvedCommentEntry"
"ide/review-panel/directives/resolvedCommentsDropdown"
"ide/review-panel/directives/reviewPanelCollapseHeight"

View file

@ -0,0 +1,10 @@
define [
"base"
], (App) ->
App.controller "BulkActionsModalController", ($scope, $modalInstance, isAccept, nChanges) ->
$scope.isAccept = isAccept
$scope.nChanges = nChanges
$scope.cancel = () ->
$modalInstance.dismiss()
$scope.confirm = () ->
$modalInstance.close(isAccept)

View file

@ -26,6 +26,7 @@ define [
resolvedThreadIds: {}
rendererData: {}
loadingThreads: false
selectedEntryIds: []
window.addEventListener "beforeunload", () ->
collapsedStates = {}
@ -176,7 +177,7 @@ define [
entries = $scope.reviewPanel.entries[$scope.editor.open_doc_id] or {}
permEntries = {}
for entry, entryData of entries
if entry != "add-comment"
if entry not in [ "add-comment", "bulk-actions" ]
permEntries[entry] = entryData
Object.keys(permEntries).length
), (nEntries) ->
@ -294,23 +295,35 @@ define [
$scope.$on "editor:focus:changed", (e, selection_offset_start, selection_offset_end, selection) ->
doc_id = $scope.editor.open_doc_id
entries = getDocEntries(doc_id)
$scope.reviewPanel.selectedEntryIds = []
delete entries["add-comment"]
delete entries["bulk-actions"]
if selection
entries["add-comment"] = {
type: "add-comment"
offset: selection_offset_start
length: selection_offset_end - selection_offset_start
}
entries["bulk-actions"] = {
type: "bulk-actions"
offset: selection_offset_start
length: selection_offset_end - selection_offset_start
}
for id, entry of entries
if entry.type == "comment" and not $scope.reviewPanel.resolvedThreadIds[entry.thread_id]
entry.focused = (entry.offset <= selection_offset_start <= entry.offset + entry.content.length)
else if entry.type == "insert"
isEntryWithinSelection = entry.offset >= selection_offset_start and entry.offset + entry.content.length <= selection_offset_end
entry.focused = (entry.offset <= selection_offset_start <= entry.offset + entry.content.length)
$scope.reviewPanel.selectedEntryIds.push id if isEntryWithinSelection
else if entry.type == "delete"
isEntryWithinSelection = selection_offset_start <= entry.offset <= selection_offset_end
entry.focused = (entry.offset == selection_offset_start)
else if entry.type == "add-comment" and selection
$scope.reviewPanel.selectedEntryIds.push id if isEntryWithinSelection
else if entry.type in [ "add-comment", "bulk-actions" ] and selection
entry.focused = true
$scope.$broadcast "review-panel:recalculate-screen-positions"
@ -325,6 +338,43 @@ define [
$scope.$broadcast "change:reject", entry_id
event_tracking.sendMB "rp-change-rejected", { view: if $scope.ui.reviewPanelOpen then $scope.reviewPanel.subView else 'mini' }
bulkAccept = () ->
entry_ids = $scope.reviewPanel.selectedEntryIds.slice()
$http.post "/project/#{$scope.project_id}/doc/#{$scope.editor.open_doc_id}/changes/accept", { change_ids: entry_ids, _csrf: window.csrfToken}
$scope.$broadcast "change:bulk-accept", entry_ids
$scope.reviewPanel.selectedEntryIds = []
event_tracking.sendMB "rp-bulk-accept", {
view: if $scope.ui.reviewPanelOpen then $scope.reviewPanel.subView else 'mini',
nEntries: $scope.reviewPanel.selectedEntryIds.length
}
bulkReject = () ->
$scope.$broadcast "change:bulk-reject", $scope.reviewPanel.selectedEntryIds.slice()
$scope.reviewPanel.selectedEntryIds = []
event_tracking.sendMB "rp-bulk-reject", {
view: if $scope.ui.reviewPanelOpen then $scope.reviewPanel.subView else 'mini',
nEntries: $scope.reviewPanel.selectedEntryIds.length
}
$scope.showBulkAcceptDialog = () ->
showBulkActionsDialog true
$scope.showBulkRejectDialog = () -> showBulkActionsDialog false
showBulkActionsDialog = (isAccept) ->
$modal.open({
templateUrl: "bulkActionsModalTemplate"
controller: "BulkActionsModalController"
resolve:
isAccept: () -> isAccept
nChanges: () -> $scope.reviewPanel.selectedEntryIds.length
scope: $scope.$new()
}).result.then (isAccept) ->
if isAccept
bulkAccept()
else
bulkReject()
$scope.addNewComment = () ->
$scope.$broadcast "comment:start_adding"
$scope.toggleReviewPanel()

View file

@ -0,0 +1,15 @@
define [
"base"
], (App) ->
App.directive "bulkActionsEntry", () ->
restrict: "E"
templateUrl: "bulkActionsEntryTemplate"
scope:
onBulkAccept: "&"
onBulkReject: "&"
nEntries: "="
link: (scope, element, attrs) ->
scope.bulkAccept = () ->
scope.onBulkAccept()
scope.bulkReject = () ->
scope.onBulkReject()

View file

@ -277,6 +277,9 @@
right: 5px;
}
}
&-bulk-actions {
right: auto;
}
}
.rp-state-overview & {
border-radius: 0;
@ -335,6 +338,12 @@
border-left-color: @rp-yellow;
}
}
&-bulk-actions {
background-color: transparent;
right: auto;
border-left-width: 0;
}
}
.rp-entry-body {
display: flex;
@ -451,17 +460,35 @@
padding: 0 5px;
}
.rp-add-comment-btn {
.rp-add-comment-btn,
.rp-bulk-actions-btn {
.rp-button();
display: block;
display: inline-block;
padding: 5px 10px;
border-radius: 3px;
.rp-in-editor-widgets & {
display: block;
white-space: nowrap;
border-radius: 0;
&:last-child {
border-bottom-left-radius: 3px;
}
}
}
.rp-bulk-actions-btn {
border-radius: 0;
&:first-child {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
&:last-child {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
margin-left: 1px;
}
}
.rp-new-comment {
@ -903,6 +930,9 @@
.rp-size-mini & {
right: @review-off-width;
}
.rp-size-expanded & {
display: none;
}
}
.rp-track-changes-indicator {
display: block;
@ -931,10 +961,6 @@
background-color: rgba(240, 240, 240, 1);
color: @rp-type-blue;
}
.rp-size-expanded & {
display: none;
}
}
// Helper class for elements which aren't treated as flex-items by IE10, e.g: