Commit 9092bed9 authored by Tiago Botelho's avatar Tiago Botelho
Browse files

Adds the functionality to convert a non-discussion into a discussion

parent 452fd703
......@@ -44,6 +44,10 @@ export default {
type: Boolean,
required: true,
},
canConvertToDiscussion: {
type: Boolean,
required: true,
},
canAwardEmoji: {
type: Boolean,
required: true,
......@@ -113,6 +117,9 @@ export default {
this.resolvedDiscussionSvg = resolvedDiscussionSvg;
},
methods: {
onConvertToDiscussion() {
this.$emit('handleConvertToDiscussion');
},
onEdit() {
this.$emit('handleEdit');
},
......@@ -186,6 +193,23 @@ export default {
</span>
</a>
</div>
<div
v-if="canConvertToDiscussion"
class="note-actions-item">
<button
v-tooltip
type="button"
title="Start a discussion"
class="note-action-button js-note-edit btn btn-transparent"
data-container="body"
data-placement="bottom"
@click="onConvertToDiscussion">
<span
class="link-highlight"
v-html="editSvg">
</span>
</button>
</div>
<div
v-if="canEdit"
class="note-actions-item">
......
......@@ -28,6 +28,7 @@ export default {
},
data() {
return {
isConverting: false,
isEditing: false,
isDeleting: false,
isRequesting: false,
......@@ -42,12 +43,16 @@ export default {
classNameBindings() {
return {
[`note-row-${this.note.id}`]: true,
'is-converting': this.isConverting && !this.isRequesting,
'is-editing': this.isEditing && !this.isRequesting,
'is-requesting being-posted': this.isRequesting,
'disabled-content': this.isDeleting,
target: this.isTarget,
};
},
canConvertToDiscussion() {
return !this.note.resolvable && !!this.getUserData.id;
},
canResolve() {
return this.note.resolvable && !!this.getUserData.id;
},
......@@ -78,10 +83,30 @@ export default {
},
methods: {
...mapActions(['deleteNote', 'updateNote', 'toggleResolveNote', 'scrollToNoteIfNeeded']),
...mapActions(['convertToDiscussion', 'deleteNote', 'updateNote', 'toggleResolveNote', 'scrollToNoteIfNeeded']),
editHandler() {
this.isEditing = true;
},
convertToDiscussionHandler() {
const data = {
endpoint: `${this.note.path}/convert`,
note: {
target_type: this.getNoteableData.targetType,
target_id: this.note.noteable_id,
},
};
this.isConverting = true;
this.convertToDiscussion(data)
.then(() => {
this.isConverting = false;
})
.catch(() => {
Flash('Something went wrong while converting to a discussion. Please try again.');
this.isConverting = false;
})
},
deleteHandler() {
// eslint-disable-next-line no-alert
if (window.confirm('Are you sure you want to delete this comment?')) {
......@@ -183,6 +208,7 @@ export default {
:access-level="note.human_access"
:can-edit="note.current_user.can_edit"
:can-award-emoji="note.current_user.can_award_emoji"
:can-convert-to-discussion="canConvertToDiscussion"
:can-delete="note.current_user.can_edit"
:can-report-as-abuse="canReportAsAbuse"
:can-resolve="note.current_user.can_resolve"
......@@ -194,6 +220,7 @@ export default {
@handleEdit="editHandler"
@handleDelete="deleteHandler"
@handleResolve="resolveHandler"
@handleConvertToDiscussion="convertToDiscussionHandler"
/>
</div>
<note-body
......
......@@ -8,6 +8,9 @@ export default {
fetchDiscussions(endpoint) {
return Vue.http.get(endpoint);
},
convertToDiscussion(endpoint, data) {
return Vue.http.post(endpoint, data, { emulateJSON: true });
},
deleteNote(endpoint) {
return Vue.http.delete(endpoint);
},
......
......@@ -52,6 +52,14 @@ export const refetchDiscussionById = ({ commit }, { path, discussionId }) =>
if (selectedDiscussion) commit(types.UPDATE_DISCUSSION, selectedDiscussion);
});
export const convertToDiscussion = ({ commit }, { endpoint, note }) =>
service
.convertToDiscussion(endpoint)
.then(res => res.json())
.then(res => {
commit(types.CONVERT_TO_DISCUSSION, res)
});
export const deleteNote = ({ commit }, note) =>
service.deleteNote(note.path).then(() => {
commit(types.DELETE_NOTE, note);
......
export const ADD_NEW_NOTE = 'ADD_NEW_NOTE';
export const ADD_NEW_REPLY_TO_DISCUSSION = 'ADD_NEW_REPLY_TO_DISCUSSION';
export const CONVERT_TO_DISCUSSION = 'CONVERT_TO_DISCUSSION';
export const DELETE_NOTE = 'DELETE_NOTE';
export const REMOVE_PLACEHOLDER_NOTES = 'REMOVE_PLACEHOLDER_NOTES';
export const SET_NOTES_DATA = 'SET_NOTES_DATA';
......
......@@ -18,6 +18,23 @@ class Projects::NotesController < Projects::ApplicationController
end
end
def convert
return render_404 if note.resolvable?
Notes::ConvertService.new(project, current_user).execute(note)
discussion = note.discussion
if serialize_notes?
render_json_with_notes_serializer
else
render json: {
resolved_by: note.resolved_by.try(:name),
discussion_headline_html: (view_to_html_string('discussions/_headline', discussion: discussion) if discussion)
}
end
end
def resolve
return render_404 unless note.resolvable?
......
module Notes
class ConvertService < ::BaseService
def execute(note)
note.update!(type: DiscussionNote.to_s)
end
end
end
......@@ -390,6 +390,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
member do
delete :delete_attachment
post :resolve
post :convert
delete :resolve, action: :unresolve
end
end
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment