Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
dd7f1df9
Commit
dd7f1df9
authored
Aug 26, 2019
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab-ce master
parents
09df224a
f5fa604c
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
198 additions
and
32 deletions
+198
-32
.gitlab/ci/reports.gitlab-ci.yml
.gitlab/ci/reports.gitlab-ci.yml
+1
-0
app/assets/javascripts/lib/utils/http_status.js
app/assets/javascripts/lib/utils/http_status.js
+1
-0
app/assets/javascripts/notes/components/noteable_note.vue
app/assets/javascripts/notes/components/noteable_note.vue
+22
-9
app/assets/javascripts/notes/stores/actions.js
app/assets/javascripts/notes/stores/actions.js
+13
-9
app/controllers/concerns/notes_actions.rb
app/controllers/concerns/notes_actions.rb
+5
-0
app/controllers/projects/notes_controller.rb
app/controllers/projects/notes_controller.rb
+1
-1
app/services/notes/update_service.rb
app/services/notes/update_service.rb
+56
-10
changelogs/unreleased/21505-quickactions-update-pd.yml
changelogs/unreleased/21505-quickactions-update-pd.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
spec/javascripts/notes/stores/actions_spec.js
spec/javascripts/notes/stores/actions_spec.js
+42
-3
spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb
.../quick_actions/issue/move_quick_action_shared_examples.rb
+49
-0
No files found.
.gitlab/ci/reports.gitlab-ci.yml
View file @
dd7f1df9
...
@@ -19,6 +19,7 @@ sast:
...
@@ -19,6 +19,7 @@ sast:
cache
:
{}
cache
:
{}
variables
:
variables
:
SAST_BRAKEMAN_LEVEL
:
2
SAST_BRAKEMAN_LEVEL
:
2
SAST_EXCLUDED_PATHS
:
qa,spec,doc
dependency_scanning
:
dependency_scanning
:
extends
:
.dedicated-no-docs
extends
:
.dedicated-no-docs
...
...
app/assets/javascripts/lib/utils/http_status.js
View file @
dd7f1df9
...
@@ -19,6 +19,7 @@ const httpStatusCodes = {
...
@@ -19,6 +19,7 @@ const httpStatusCodes = {
UNAUTHORIZED
:
401
,
UNAUTHORIZED
:
401
,
FORBIDDEN
:
403
,
FORBIDDEN
:
403
,
NOT_FOUND
:
404
,
NOT_FOUND
:
404
,
GONE
:
410
,
UNPROCESSABLE_ENTITY
:
422
,
UNPROCESSABLE_ENTITY
:
422
,
};
};
...
...
app/assets/javascripts/notes/components/noteable_note.vue
View file @
dd7f1df9
...
@@ -14,6 +14,7 @@ import NoteBody from './note_body.vue';
...
@@ -14,6 +14,7 @@ import NoteBody from './note_body.vue';
import
eventHub
from
'
../event_hub
'
;
import
eventHub
from
'
../event_hub
'
;
import
noteable
from
'
../mixins/noteable
'
;
import
noteable
from
'
../mixins/noteable
'
;
import
resolvable
from
'
../mixins/resolvable
'
;
import
resolvable
from
'
../mixins/resolvable
'
;
import
httpStatusCodes
from
'
~/lib/utils/http_status
'
;
export
default
{
export
default
{
name
:
'
NoteableNote
'
,
name
:
'
NoteableNote
'
,
...
@@ -122,7 +123,13 @@ export default {
...
@@ -122,7 +123,13 @@ export default {
},
},
methods
:
{
methods
:
{
...
mapActions
([
'
deleteNote
'
,
'
updateNote
'
,
'
toggleResolveNote
'
,
'
scrollToNoteIfNeeded
'
]),
...
mapActions
([
'
deleteNote
'
,
'
removeNote
'
,
'
updateNote
'
,
'
toggleResolveNote
'
,
'
scrollToNoteIfNeeded
'
,
]),
editHandler
()
{
editHandler
()
{
this
.
isEditing
=
true
;
this
.
isEditing
=
true
;
this
.
$emit
(
'
handleEdit
'
);
this
.
$emit
(
'
handleEdit
'
);
...
@@ -185,15 +192,21 @@ export default {
...
@@ -185,15 +192,21 @@ export default {
this
.
updateSuccess
();
this
.
updateSuccess
();
callback
();
callback
();
})
})
.
catch
(()
=>
{
.
catch
(
response
=>
{
this
.
isRequesting
=
false
;
if
(
response
.
status
===
httpStatusCodes
.
GONE
)
{
this
.
isEditing
=
true
;
this
.
removeNote
(
this
.
note
);
this
.
$nextTick
(()
=>
{
this
.
updateSuccess
();
const
msg
=
__
(
'
Something went wrong while editing your comment. Please try again.
'
);
Flash
(
msg
,
'
alert
'
,
this
.
$el
);
this
.
recoverNoteContent
(
noteText
);
callback
();
callback
();
});
}
else
{
this
.
isRequesting
=
false
;
this
.
isEditing
=
true
;
this
.
$nextTick
(()
=>
{
const
msg
=
__
(
'
Something went wrong while editing your comment. Please try again.
'
);
Flash
(
msg
,
'
alert
'
,
this
.
$el
);
this
.
recoverNoteContent
(
noteText
);
callback
();
});
}
});
});
},
},
formCancelHandler
(
shouldConfirm
,
isDirty
)
{
formCancelHandler
(
shouldConfirm
,
isDirty
)
{
...
...
app/assets/javascripts/notes/stores/actions.js
View file @
dd7f1df9
...
@@ -61,18 +61,22 @@ export const updateDiscussion = ({ commit, state }, discussion) => {
...
@@ -61,18 +61,22 @@ export const updateDiscussion = ({ commit, state }, discussion) => {
return
utils
.
findNoteObjectById
(
state
.
discussions
,
discussion
.
id
);
return
utils
.
findNoteObjectById
(
state
.
discussions
,
discussion
.
id
);
};
};
export
const
deleteNote
=
({
commit
,
dispatch
,
state
},
note
)
=>
export
const
removeNote
=
({
commit
,
dispatch
,
state
},
note
)
=>
{
axios
.
delete
(
note
.
path
).
then
(()
=>
{
const
discussion
=
state
.
discussions
.
find
(({
id
})
=>
id
===
note
.
discussion_id
);
const
discussion
=
state
.
discussions
.
find
(({
id
})
=>
id
===
note
.
discussion_id
);
commit
(
types
.
DELETE_NOTE
,
note
);
commit
(
types
.
DELETE_NOTE
,
note
);
dispatch
(
'
updateMergeRequestWidget
'
);
dispatch
(
'
updateMergeRequestWidget
'
);
dispatch
(
'
updateResolvableDiscussionsCounts
'
);
dispatch
(
'
updateResolvableDiscussionsCounts
'
);
if
(
isInMRPage
())
{
if
(
isInMRPage
())
{
dispatch
(
'
diffs/removeDiscussionsFromDiff
'
,
discussion
);
dispatch
(
'
diffs/removeDiscussionsFromDiff
'
,
discussion
);
}
}
};
export
const
deleteNote
=
({
dispatch
},
note
)
=>
axios
.
delete
(
note
.
path
).
then
(()
=>
{
dispatch
(
'
removeNote
'
,
note
);
});
});
export
const
updateNote
=
({
commit
,
dispatch
},
{
endpoint
,
note
})
=>
export
const
updateNote
=
({
commit
,
dispatch
},
{
endpoint
,
note
})
=>
...
...
app/controllers/concerns/notes_actions.rb
View file @
dd7f1df9
...
@@ -73,6 +73,11 @@ module NotesActions
...
@@ -73,6 +73,11 @@ module NotesActions
# rubocop:disable Gitlab/ModuleWithInstanceVariables
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def
update
def
update
@note
=
Notes
::
UpdateService
.
new
(
project
,
current_user
,
update_note_params
).
execute
(
note
)
@note
=
Notes
::
UpdateService
.
new
(
project
,
current_user
,
update_note_params
).
execute
(
note
)
unless
@note
head
:gone
return
end
prepare_notes_for_rendering
([
@note
])
prepare_notes_for_rendering
([
@note
])
respond_to
do
|
format
|
respond_to
do
|
format
|
...
...
app/controllers/projects/notes_controller.rb
View file @
dd7f1df9
...
@@ -6,7 +6,7 @@ class Projects::NotesController < Projects::ApplicationController
...
@@ -6,7 +6,7 @@ class Projects::NotesController < Projects::ApplicationController
include
NotesHelper
include
NotesHelper
include
ToggleAwardEmoji
include
ToggleAwardEmoji
before_action
:whitelist_query_limiting
,
only:
[
:create
]
before_action
:whitelist_query_limiting
,
only:
[
:create
,
:update
]
before_action
:authorize_read_note!
before_action
:authorize_read_note!
before_action
:authorize_create_note!
,
only:
[
:create
]
before_action
:authorize_create_note!
,
only:
[
:create
]
before_action
:authorize_resolve_note!
,
only:
[
:resolve
,
:unresolve
]
before_action
:authorize_resolve_note!
,
only:
[
:resolve
,
:unresolve
]
...
...
app/services/notes/update_service.rb
View file @
dd7f1df9
...
@@ -8,24 +8,70 @@ module Notes
...
@@ -8,24 +8,70 @@ module Notes
old_mentioned_users
=
note
.
mentioned_users
.
to_a
old_mentioned_users
=
note
.
mentioned_users
.
to_a
note
.
update
(
params
.
merge
(
updated_by:
current_user
))
note
.
update
(
params
.
merge
(
updated_by:
current_user
))
note
.
create_new_cross_references!
(
current_user
)
if
note
.
previous_changes
.
include?
(
'note'
)
only_commands
=
false
TodoService
.
new
.
update_note
(
note
,
current_user
,
old_mentioned_users
)
quick_actions_service
=
QuickActionsService
.
new
(
project
,
current_user
)
if
quick_actions_service
.
supported?
(
note
)
content
,
update_params
,
message
=
quick_actions_service
.
execute
(
note
,
{})
only_commands
=
content
.
empty?
note
.
note
=
content
end
unless
only_commands
note
.
create_new_cross_references!
(
current_user
)
update_todos
(
note
,
old_mentioned_users
)
update_suggestions
(
note
)
end
end
if
note
.
supports_suggestion?
if
quick_actions_service
.
commands_executed_count
.
to_i
>
0
Suggestion
.
transaction
do
if
update_params
.
present?
note
.
suggestions
.
delete_all
quick_actions_service
.
apply_updates
(
update_params
,
note
)
Suggestions
::
CreateService
.
new
(
note
).
execute
note
.
commands_changes
=
update_params
end
end
# We need to refresh the previous suggestions call cache
if
only_commands
# in order to get the new records.
delete_note
(
note
,
message
)
note
.
reset
note
=
nil
else
note
.
save
end
end
end
note
note
end
end
private
def
delete_note
(
note
,
message
)
# We must add the error after we call #save because errors are reset
# when #save is called
note
.
errors
.
add
(
:commands_only
,
message
.
presence
||
_
(
'Commands did not apply'
))
Notes
::
DestroyService
.
new
(
project
,
current_user
).
execute
(
note
)
end
def
update_suggestions
(
note
)
return
unless
note
.
supports_suggestion?
Suggestion
.
transaction
do
note
.
suggestions
.
delete_all
Suggestions
::
CreateService
.
new
(
note
).
execute
end
# We need to refresh the previous suggestions call cache
# in order to get the new records.
note
.
reset
end
def
update_todos
(
note
,
old_mentioned_users
)
return
unless
note
.
previous_changes
.
include?
(
'note'
)
TodoService
.
new
.
update_note
(
note
,
current_user
,
old_mentioned_users
)
end
end
end
end
end
changelogs/unreleased/21505-quickactions-update-pd.yml
0 → 100644
View file @
dd7f1df9
---
title
:
Apply quickactions when modifying comments
merge_request
:
31136
author
:
type
:
added
locale/gitlab.pot
View file @
dd7f1df9
...
@@ -3697,6 +3697,9 @@ msgstr ""
...
@@ -3697,6 +3697,9 @@ msgstr ""
msgid "Commands applied"
msgid "Commands applied"
msgstr ""
msgstr ""
msgid "Commands did not apply"
msgstr ""
msgid "Comment"
msgid "Comment"
msgstr ""
msgstr ""
...
...
spec/javascripts/notes/stores/actions_spec.js
View file @
dd7f1df9
...
@@ -336,7 +336,7 @@ describe('Actions Notes Store', () => {
...
@@ -336,7 +336,7 @@ describe('Actions Notes Store', () => {
});
});
});
});
describe
(
'
delet
eNote
'
,
()
=>
{
describe
(
'
remov
eNote
'
,
()
=>
{
const
endpoint
=
`
${
TEST_HOST
}
/note`
;
const
endpoint
=
`
${
TEST_HOST
}
/note`
;
let
axiosMock
;
let
axiosMock
;
...
@@ -357,7 +357,7 @@ describe('Actions Notes Store', () => {
...
@@ -357,7 +357,7 @@ describe('Actions Notes Store', () => {
const
note
=
{
path
:
endpoint
,
id
:
1
};
const
note
=
{
path
:
endpoint
,
id
:
1
};
testAction
(
testAction
(
actions
.
delet
eNote
,
actions
.
remov
eNote
,
note
,
note
,
store
.
state
,
store
.
state
,
[
[
...
@@ -384,7 +384,7 @@ describe('Actions Notes Store', () => {
...
@@ -384,7 +384,7 @@ describe('Actions Notes Store', () => {
$
(
'
body
'
).
attr
(
'
data-page
'
,
'
projects:merge_requests:show
'
);
$
(
'
body
'
).
attr
(
'
data-page
'
,
'
projects:merge_requests:show
'
);
testAction
(
testAction
(
actions
.
delet
eNote
,
actions
.
remov
eNote
,
note
,
note
,
store
.
state
,
store
.
state
,
[
[
...
@@ -409,6 +409,45 @@ describe('Actions Notes Store', () => {
...
@@ -409,6 +409,45 @@ describe('Actions Notes Store', () => {
});
});
});
});
describe
(
'
deleteNote
'
,
()
=>
{
const
endpoint
=
`
${
TEST_HOST
}
/note`
;
let
axiosMock
;
beforeEach
(()
=>
{
axiosMock
=
new
AxiosMockAdapter
(
axios
);
axiosMock
.
onDelete
(
endpoint
).
replyOnce
(
200
,
{});
$
(
'
body
'
).
attr
(
'
data-page
'
,
''
);
});
afterEach
(()
=>
{
axiosMock
.
restore
();
$
(
'
body
'
).
attr
(
'
data-page
'
,
''
);
});
it
(
'
dispatches removeNote
'
,
done
=>
{
const
note
=
{
path
:
endpoint
,
id
:
1
};
testAction
(
actions
.
deleteNote
,
note
,
{},
[],
[
{
type
:
'
removeNote
'
,
payload
:
{
id
:
1
,
path
:
'
http://test.host/note
'
,
},
},
],
done
,
);
});
});
describe
(
'
createNewNote
'
,
()
=>
{
describe
(
'
createNewNote
'
,
()
=>
{
describe
(
'
success
'
,
()
=>
{
describe
(
'
success
'
,
()
=>
{
const
res
=
{
const
res
=
{
...
...
spec/support/shared_examples/quick_actions/issue/move_quick_action_shared_examples.rb
View file @
dd7f1df9
...
@@ -89,5 +89,54 @@ shared_examples 'move quick action' do
...
@@ -89,5 +89,54 @@ shared_examples 'move quick action' do
it_behaves_like
'applies the commands to issues in both projects, target and source'
it_behaves_like
'applies the commands to issues in both projects, target and source'
end
end
end
end
context
'when editing comments'
do
let
(
:target_project
)
{
create
(
:project
,
:public
)
}
before
do
target_project
.
add_maintainer
(
user
)
sign_in
(
user
)
visit
project_issue_path
(
project
,
issue
)
wait_for_all_requests
end
it
'moves the issue after quickcommand note was updated'
do
# misspelled quick action
add_note
(
"test note.
\n
/mvoe
#{
target_project
.
full_path
}
"
)
expect
(
issue
.
reload
).
not_to
be_closed
edit_note
(
"/mvoe
#{
target_project
.
full_path
}
"
,
"test note.
\n
/move
#{
target_project
.
full_path
}
"
)
wait_for_all_requests
expect
(
page
).
to
have_content
'test note.'
expect
(
issue
.
reload
).
to
be_closed
visit
project_issue_path
(
target_project
,
issue
)
wait_for_all_requests
expect
(
page
).
to
have_content
'Issues 1'
end
it
'deletes the note if it was updated to just contain a command'
do
# missspelled quick action
add_note
(
"test note.
\n
/mvoe
#{
target_project
.
full_path
}
"
)
expect
(
page
).
not_to
have_content
'Commands applied'
expect
(
issue
.
reload
).
not_to
be_closed
edit_note
(
"/mvoe
#{
target_project
.
full_path
}
"
,
"/move
#{
target_project
.
full_path
}
"
)
wait_for_all_requests
expect
(
page
).
not_to
have_content
"/move
#{
target_project
.
full_path
}
"
expect
(
issue
.
reload
).
to
be_closed
visit
project_issue_path
(
target_project
,
issue
)
wait_for_all_requests
expect
(
page
).
to
have_content
'Issues 1'
end
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment