From f7344338985338df3d0958ef9d362b9624723e0f Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Fri, 9 Jun 2017 01:49:49 +0300 Subject: [PATCH 001/243] Add Vuex as a dependency. --- package.json | 1 + yarn.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/package.json b/package.json index fd944531a6a..6117bbcbe2a 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "vue-loader": "^11.3.4", "vue-resource": "^1.3.4", "vue-template-compiler": "^2.2.6", + "vuex": "^2.3.1", "webpack": "^2.6.1", "webpack-bundle-analyzer": "^2.8.2" }, diff --git a/yarn.lock b/yarn.lock index 98da6a984d1..075bf70a641 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5775,6 +5775,10 @@ vue@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/vue/-/vue-2.2.6.tgz#451714b394dd6d4eae7b773c40c2034a59621aed" +vuex@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-2.3.1.tgz#cde8e997c1f9957719bc7dea154f9aa691d981a6" + watchpack@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87" From cb2287df0ad9396d1f075bde1c4f6de481d908e6 Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Fri, 9 Jun 2017 01:50:11 +0300 Subject: [PATCH 002/243] Notes bundle for the issue discussions refactor. --- app/assets/javascripts/notes/index.js | 8 ++++++++ app/views/projects/issues/_discussion.html.haml | 5 +++++ config/webpack.config.js | 2 ++ 3 files changed, 15 insertions(+) create mode 100644 app/assets/javascripts/notes/index.js diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js new file mode 100644 index 00000000000..4ee2cf19cf0 --- /dev/null +++ b/app/assets/javascripts/notes/index.js @@ -0,0 +1,8 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; + +Vue.use(Vuex); + +document.addEventListener('DOMContentLoaded', () => { + // instantiate Vue here... +}); diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index 8b095f4ca10..f1711bf074e 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -3,5 +3,10 @@ = link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, format: 'json'), data: {original_text: "Reopen issue", alternative_text: "Comment & reopen issue"}, class: "btn btn-nr btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue' = link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue' +#js-notes + - content_for :page_specific_javascripts do + = webpack_bundle_tag 'common_vue' + = webpack_bundle_tag 'notes' + #notes = render 'shared/notes/notes_with_form', :autocomplete => true diff --git a/config/webpack.config.js b/config/webpack.config.js index a7d92bc53b7..bcc64b1fccd 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -51,6 +51,7 @@ var config = { monitoring: './monitoring/monitoring_bundle.js', network: './network/network_bundle.js', notebook_viewer: './blob/notebook_viewer.js', + notes: './notes/index.js', pdf_viewer: './blob/pdf_viewer.js', pipelines: './pipelines/pipelines_bundle.js', pipelines_details: './pipelines/pipeline_details_bundle.js', @@ -166,6 +167,7 @@ var config = { 'merge_conflicts', 'monitoring', 'notebook_viewer', + 'notes', 'pdf_viewer', 'pipelines', 'pipelines_details', From 76c3d2d434d3c550c3de912abc0a5b1dc1455368 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 9 Jun 2017 16:24:54 -0500 Subject: [PATCH 003/243] Add full JSON endpoints for issue notes and discussions --- app/controllers/concerns/notes_actions.rb | 49 ++++++++++------ app/controllers/projects/issues_controller.rb | 8 +++ app/helpers/issues_helper.rb | 2 +- app/helpers/system_note_helper.rb | 8 ++- app/models/discussion.rb | 4 ++ app/serializers/award_emoji_entity.rb | 4 ++ app/serializers/discussion_entity.rb | 20 +++++++ app/serializers/discussion_serializer.rb | 3 + app/serializers/note_attachment_entity.rb | 5 ++ app/serializers/note_entity.rb | 58 +++++++++++++++++++ app/serializers/note_serializer.rb | 3 + app/serializers/user_entity.rb | 2 + app/views/discussions/_headline.html.haml | 2 +- config/routes/project.rb | 1 + lib/api/entities.rb | 4 +- 15 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 app/serializers/award_emoji_entity.rb create mode 100644 app/serializers/discussion_entity.rb create mode 100644 app/serializers/discussion_serializer.rb create mode 100644 app/serializers/note_attachment_entity.rb create mode 100644 app/serializers/note_entity.rb create mode 100644 app/serializers/note_serializer.rb diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb index a57d9e6e6c0..14e755c8d97 100644 --- a/app/controllers/concerns/notes_actions.rb +++ b/app/controllers/concerns/notes_actions.rb @@ -11,14 +11,16 @@ module NotesActions notes_json = { notes: [], last_fetched_at: current_fetched_at } - @notes = notes_finder.execute.inc_relations_for_view + @notes = notes_finder.execute.inc_relations_for_view.to_a + @notes.reject! { |n| n.cross_reference_not_visible_for?(current_user) } @notes = prepare_notes_for_rendering(@notes) - @notes.each do |note| - next if note.cross_reference_not_visible_for?(current_user) - - notes_json[:notes] << note_json(note) - end + notes_json[:notes] = + if params[:full_data] + note_serializer.represent(@notes) + else + @notes.map { |note| note_json(note) } + end render json: notes_json end @@ -80,22 +82,27 @@ module NotesActions } if note.persisted? - attrs.merge!( - valid: true, - id: note.id, - discussion_id: note.discussion_id(noteable), - html: note_html(note), - note: note.note - ) + attrs[:valid] = true - discussion = note.to_discussion(noteable) - unless discussion.individual_note? + if params[:full_data] + attrs.merge!(note_serializer.represent(note)) + else attrs.merge!( - discussion_resolvable: discussion.resolvable?, - - diff_discussion_html: diff_discussion_html(discussion), - discussion_html: discussion_html(discussion) + id: note.id, + discussion_id: note.discussion_id(noteable), + html: note_html(note), + note: note.note ) + + discussion = note.to_discussion(noteable) + unless discussion.individual_note? + attrs.merge!( + discussion_resolvable: discussion.resolvable?, + + diff_discussion_html: diff_discussion_html(discussion), + discussion_html: discussion_html(discussion) + ) + end end else attrs.merge!( @@ -177,4 +184,8 @@ module NotesActions def notes_finder @notes_finder ||= NotesFinder.new(project, current_user, finder_params) end + + def note_serializer + NoteSerializer.new(project: project, noteable: noteable, current_user: current_user) + end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 0ac9da2ff0f..153c490ce3f 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -97,6 +97,14 @@ class Projects::IssuesController < Projects::ApplicationController end end + def discussions + @discussions = @issue.discussions + @discussions.reject! { |d| d.individual_note? && d.first_note.cross_reference_not_visible_for?(current_user) } + prepare_notes_for_rendering(@discussions.flat_map(&:notes)) + + render json: DiscussionSerializer.new(project: @project, noteable: @issue, current_user: current_user).represent(@discussions) + end + def create create_params = issue_params.merge(spammable_params).merge( merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of], diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 42b6cfdf02f..034b4451b56 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -119,7 +119,7 @@ module IssuesHelper end def awards_sort(awards) - awards.sort_by do |award, notes| + awards.sort_by do |award, award_emojis| if award == "thumbsup" 0 elsif award == "thumbsdown" diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb index 209bd56b78a..69366825124 100644 --- a/app/helpers/system_note_helper.rb +++ b/app/helpers/system_note_helper.rb @@ -21,8 +21,14 @@ module SystemNoteHelper 'outdated' => 'icon_edit' }.freeze + def system_note_icon_name(note) + ICON_NAMES_BY_ACTION[note.system_note_metadata&.action] + end + def icon_for_system_note(note) - icon_name = ICON_NAMES_BY_ACTION[note.system_note_metadata&.action] + icon_name = system_note_icon_name(note) custom_icon(icon_name) if icon_name end + + extend self end diff --git a/app/models/discussion.rb b/app/models/discussion.rb index d1cec7613af..b80da7b246a 100644 --- a/app/models/discussion.rb +++ b/app/models/discussion.rb @@ -81,6 +81,10 @@ class Discussion last_note.author end + def updated? + last_updated_at != created_at + end + def id first_note.discussion_id(context_noteable) end diff --git a/app/serializers/award_emoji_entity.rb b/app/serializers/award_emoji_entity.rb new file mode 100644 index 00000000000..6e03cd02392 --- /dev/null +++ b/app/serializers/award_emoji_entity.rb @@ -0,0 +1,4 @@ +class AwardEmojiEntity < Grape::Entity + expose :name + expose :user, using: API::Entities::UserSafe +end diff --git a/app/serializers/discussion_entity.rb b/app/serializers/discussion_entity.rb new file mode 100644 index 00000000000..cb6c3c23807 --- /dev/null +++ b/app/serializers/discussion_entity.rb @@ -0,0 +1,20 @@ +class DiscussionEntity < Grape::Entity + include RequestAwareEntity + + expose :id, :reply_id + expose :expanded?, as: :expanded + expose :author, using: UserEntity + + expose :created_at + + expose :last_updated_at, if: -> (discussion, _) { discussion.updated? } + expose :last_updated_by, if: -> (discussion, _) { discussion.updated? }, using: UserEntity + + expose :notes, using: NoteEntity + + expose :individual_note?, as: :individual_note + + expose :can_reply do |discussion| + can?(request.current_user, :create_note, discussion.project) + end +end diff --git a/app/serializers/discussion_serializer.rb b/app/serializers/discussion_serializer.rb new file mode 100644 index 00000000000..ed5e1224bb2 --- /dev/null +++ b/app/serializers/discussion_serializer.rb @@ -0,0 +1,3 @@ +class DiscussionSerializer < BaseSerializer + entity DiscussionEntity +end diff --git a/app/serializers/note_attachment_entity.rb b/app/serializers/note_attachment_entity.rb new file mode 100644 index 00000000000..1ad50568ab9 --- /dev/null +++ b/app/serializers/note_attachment_entity.rb @@ -0,0 +1,5 @@ +class NoteAttachmentEntity < Grape::Entity + expose :url + expose :filename + expose :image?, as: :image +end diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb new file mode 100644 index 00000000000..7a49ec4ef55 --- /dev/null +++ b/app/serializers/note_entity.rb @@ -0,0 +1,58 @@ +class NoteEntity < API::Entities::Note + include RequestAwareEntity + + expose :type + + expose :author, using: UserEntity + + expose :human_access do |note| + note.project.team.human_max_access(note.author_id) + end + + unexpose :note, as: :body + expose :note + + expose :redacted_note_html, as: :note_html + + expose :last_edited_at, if: -> (note, _) { note.is_edited? } + expose :last_edited_by, using: UserEntity, if: -> (note, _) { note.is_edited? } + + expose :can_edit do |note| + Ability.can_edit_note?(request.current_user, note) + end + + expose :system_note_icon_name, if: -> (note, _) { note.system? } do |note| + SystemNoteHelper.system_note_icon_name(note) + end + + expose :discussion_id do |note| + note.discussion_id(request.noteable) + end + + expose :emoji_awardable?, as: :emoji_awardable + expose :award_emoji, if: -> (note, _) { note.emoji_awardable? }, using: AwardEmojiEntity + expose :toggle_award_path, if: -> (note, _) { note.emoji_awardable? } do |note| + if note.for_personal_snippet? + toggle_award_emoji_snippet_note_path(note.noteable, note) + else + toggle_award_emoji_namespace_project_note_path(note.project.namespace, note.project, note.id) + end + end + + expose :report_abuse_path do |note| + new_abuse_report_path(user_id: note.author.id, ref_url: Gitlab::UrlBuilder.build(note)) + end + + expose :path do |note| + if note.for_personal_snippet? + snippet_note_path(note.noteable, note) + else + namespace_project_note_path(note.project.namespace, note.project, note) + end + end + + expose :attachment, using: NoteAttachmentEntity + expose :delete_attachment_path, if: -> (note, _) { note.attachment? } do |note| + delete_attachment_namespace_project_note_path(note.project.namespace, note.project, note) + end +end diff --git a/app/serializers/note_serializer.rb b/app/serializers/note_serializer.rb new file mode 100644 index 00000000000..2afe40d7a34 --- /dev/null +++ b/app/serializers/note_serializer.rb @@ -0,0 +1,3 @@ +class NoteSerializer < BaseSerializer + entity NoteEntity +end diff --git a/app/serializers/user_entity.rb b/app/serializers/user_entity.rb index 876512b12dc..3bb340065c4 100644 --- a/app/serializers/user_entity.rb +++ b/app/serializers/user_entity.rb @@ -1,6 +1,8 @@ class UserEntity < API::Entities::UserBasic include RequestAwareEntity + unexpose :web_url + expose :path do |user| user_path(user) end diff --git a/app/views/discussions/_headline.html.haml b/app/views/discussions/_headline.html.haml index c1dabeed387..25e90924413 100644 --- a/app/views/discussions/_headline.html.haml +++ b/app/views/discussions/_headline.html.haml @@ -5,7 +5,7 @@ by = link_to_member(@project, discussion.resolved_by, avatar: false) = time_ago_with_tooltip(discussion.resolved_at, placement: "bottom") -- elsif discussion.last_updated_at != discussion.created_at +- elsif discussion.updated? .discussion-headline-light.js-discussion-headline Last updated - if discussion.last_updated_by diff --git a/config/routes/project.rb b/config/routes/project.rb index 672b5a9a160..d6fb309de8e 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -308,6 +308,7 @@ constraints(ProjectUrlConstrainer.new) do get :can_create_branch get :realtime_changes post :create_merge_request + get :discussions, format: :json end collection do post :bulk_update diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 09a88869063..89ab2118dd5 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1,11 +1,11 @@ module API module Entities class UserSafe < Grape::Entity - expose :name, :username + expose :id, :name, :username end class UserBasic < UserSafe - expose :id, :state + expose :state expose :avatar_url do |user, options| user.avatar_url(only_path: false) end From 4b87ecd37d3ef0d0e2d0bbe59d6a4d0a409e19f9 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Fri, 9 Jun 2017 16:41:59 -0500 Subject: [PATCH 004/243] Add data-discussions-path to issues notes div --- app/views/projects/issues/_discussion.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index f1711bf074e..6d09a171b53 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -8,5 +8,5 @@ = webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'notes' -#notes +#notes{ data: { discussions_path: discussions_namespace_project_issue_path(@project.namespace, @project, @issue, format: :json) } } = render 'shared/notes/notes_with_form', :autocomplete => true From 0273b1188b939b157d439247a97e6c2d24a9f0b4 Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Sat, 10 Jun 2017 01:50:31 +0300 Subject: [PATCH 005/243] Initial version of main component, Vuex store and service of issue discussions refactor. --- .../notes/components/issue_notes.vue | 37 +++++++++++++++++++ app/assets/javascripts/notes/index.js | 14 ++++--- .../notes/services/issue_notes_service.js | 10 +++++ .../notes/stores/issue_notes_store.js | 37 +++++++++++++++++++ .../projects/issues/_discussion.html.haml | 5 ++- 5 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 app/assets/javascripts/notes/components/issue_notes.vue create mode 100644 app/assets/javascripts/notes/services/issue_notes_service.js create mode 100644 app/assets/javascripts/notes/stores/issue_notes_store.js diff --git a/app/assets/javascripts/notes/components/issue_notes.vue b/app/assets/javascripts/notes/components/issue_notes.vue new file mode 100644 index 00000000000..1b7de0b740e --- /dev/null +++ b/app/assets/javascripts/notes/components/issue_notes.vue @@ -0,0 +1,37 @@ + + + diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js index 4ee2cf19cf0..f0f94e2f500 100644 --- a/app/assets/javascripts/notes/index.js +++ b/app/assets/javascripts/notes/index.js @@ -1,8 +1,10 @@ import Vue from 'vue'; -import Vuex from 'vuex'; +import IssueNotes from './components/issue_notes.vue'; -Vue.use(Vuex); - -document.addEventListener('DOMContentLoaded', () => { - // instantiate Vue here... -}); +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '#js-notes', + components: { IssueNotes }, + template: ` + + `, +})); diff --git a/app/assets/javascripts/notes/services/issue_notes_service.js b/app/assets/javascripts/notes/services/issue_notes_service.js new file mode 100644 index 00000000000..810dec61b5b --- /dev/null +++ b/app/assets/javascripts/notes/services/issue_notes_service.js @@ -0,0 +1,10 @@ +import Vue from 'vue'; +import VueResource from 'vue-resource'; + +Vue.use(VueResource); + +export default { + fetchNotes(endpoint) { + return Vue.http.get(endpoint); + }, +}; diff --git a/app/assets/javascripts/notes/stores/issue_notes_store.js b/app/assets/javascripts/notes/stores/issue_notes_store.js new file mode 100644 index 00000000000..4b3c08e9ca8 --- /dev/null +++ b/app/assets/javascripts/notes/stores/issue_notes_store.js @@ -0,0 +1,37 @@ +/* global Flash */ +/* eslint-disable no-param-reassign */ + +import service from '../services/issue_notes_service'; + +const state = { + notes: [], +}; + +const getters = {}; + +const mutations = { + setNotes(vmState, notes) { + vmState.notes = notes; + }, +}; + +const actions = { + fetchNotes(context, path) { + return service + .fetchNotes(path) + .then(res => res.json()) + .then((res) => { + context.commit('setNotes', res); + }) + .catch(() => { + new Flash('Something went while fetching issue comments. Please try again.'); // eslint-disable-line + }); + }, +}; + +export default { + state, + getters, + mutations, + actions, +}; diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index 6d09a171b53..d5ec7fdcb3e 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -3,10 +3,11 @@ = link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, format: 'json'), data: {original_text: "Reopen issue", alternative_text: "Comment & reopen issue"}, class: "btn btn-nr btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue' = link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue' -#js-notes +%section{ data: { discussions_path: discussions_namespace_project_issue_path(@project.namespace, @project, @issue, format: :json) } } + #js-notes - content_for :page_specific_javascripts do = webpack_bundle_tag 'common_vue' = webpack_bundle_tag 'notes' -#notes{ data: { discussions_path: discussions_namespace_project_issue_path(@project.namespace, @project, @issue, format: :json) } } +#notes = render 'shared/notes/notes_with_form', :autocomplete => true From 16a5808e6061cce75f84de8cfb332ec2f5c81ef6 Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Tue, 13 Jun 2017 20:01:59 +0300 Subject: [PATCH 006/243] =?UTF-8?q?Implement=20initial=20version=20of=20Vu?= =?UTF-8?q?e=20notes=20for=20issues.=20=F0=9F=8E=89=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../notes/components/issue_discussion.vue | 112 ++++++++++++++++++ .../notes/components/issue_note.vue | 63 ++++++++++ .../notes/components/issue_note_actions.vue | 95 +++++++++++++++ .../notes/components/issue_note_body.vue | 18 +++ .../components/issue_note_edited_text.vue | 43 +++++++ .../notes/components/issue_note_header.vue | 79 ++++++++++++ .../notes/components/issue_notes.vue | 25 +++- .../icons/emoji_slightly_smiling_face.svg | 1 + .../javascripts/notes/icons/emoji_smile.svg | 1 + .../javascripts/notes/icons/emoji_smiley.svg | 1 + .../notes/stores/issue_notes_store.js | 17 ++- app/assets/stylesheets/pages/issuable.scss | 1 + .../shared/notes/_notes_with_form.html.haml | 6 +- 13 files changed, 454 insertions(+), 8 deletions(-) create mode 100644 app/assets/javascripts/notes/components/issue_discussion.vue create mode 100644 app/assets/javascripts/notes/components/issue_note.vue create mode 100644 app/assets/javascripts/notes/components/issue_note_actions.vue create mode 100644 app/assets/javascripts/notes/components/issue_note_body.vue create mode 100644 app/assets/javascripts/notes/components/issue_note_edited_text.vue create mode 100644 app/assets/javascripts/notes/components/issue_note_header.vue create mode 100644 app/assets/javascripts/notes/icons/emoji_slightly_smiling_face.svg create mode 100644 app/assets/javascripts/notes/icons/emoji_smile.svg create mode 100644 app/assets/javascripts/notes/icons/emoji_smiley.svg diff --git a/app/assets/javascripts/notes/components/issue_discussion.vue b/app/assets/javascripts/notes/components/issue_discussion.vue new file mode 100644 index 00000000000..21f1f721a05 --- /dev/null +++ b/app/assets/javascripts/notes/components/issue_discussion.vue @@ -0,0 +1,112 @@ + + + diff --git a/app/assets/javascripts/notes/components/issue_note.vue b/app/assets/javascripts/notes/components/issue_note.vue new file mode 100644 index 00000000000..7e4c6cc6eee --- /dev/null +++ b/app/assets/javascripts/notes/components/issue_note.vue @@ -0,0 +1,63 @@ + + + diff --git a/app/assets/javascripts/notes/components/issue_note_actions.vue b/app/assets/javascripts/notes/components/issue_note_actions.vue new file mode 100644 index 00000000000..35828a959e1 --- /dev/null +++ b/app/assets/javascripts/notes/components/issue_note_actions.vue @@ -0,0 +1,95 @@ + + + diff --git a/app/assets/javascripts/notes/components/issue_note_body.vue b/app/assets/javascripts/notes/components/issue_note_body.vue new file mode 100644 index 00000000000..8c12a81c2dd --- /dev/null +++ b/app/assets/javascripts/notes/components/issue_note_body.vue @@ -0,0 +1,18 @@ + + + diff --git a/app/assets/javascripts/notes/components/issue_note_edited_text.vue b/app/assets/javascripts/notes/components/issue_note_edited_text.vue new file mode 100644 index 00000000000..f1b8362ad65 --- /dev/null +++ b/app/assets/javascripts/notes/components/issue_note_edited_text.vue @@ -0,0 +1,43 @@ + + + diff --git a/app/assets/javascripts/notes/components/issue_note_header.vue b/app/assets/javascripts/notes/components/issue_note_header.vue new file mode 100644 index 00000000000..0ce07da8d3e --- /dev/null +++ b/app/assets/javascripts/notes/components/issue_note_header.vue @@ -0,0 +1,79 @@ + + + diff --git a/app/assets/javascripts/notes/components/issue_notes.vue b/app/assets/javascripts/notes/components/issue_notes.vue index 1b7de0b740e..98db5b1ec9b 100644 --- a/app/assets/javascripts/notes/components/issue_notes.vue +++ b/app/assets/javascripts/notes/components/issue_notes.vue @@ -2,6 +2,8 @@ import Vue from 'vue'; import Vuex from 'vuex'; import storeOptions from '../stores/issue_notes_store'; +import IssueNote from './issue_note.vue'; +import IssueDiscussion from './issue_discussion.vue'; Vue.use(Vuex); const store = new Vuex.Store(storeOptions); @@ -14,6 +16,18 @@ export default { isLoading: true, }; }, + components: { + IssueNote, + IssueDiscussion, + }, + methods: { + component(note) { + return note.individual_note ? IssueNote : IssueDiscussion; + }, + componentData(note) { + return note.individual_note ? note.notes[0] : note; + } + }, mounted() { const path = this.$el.parentNode.dataset.discussionsPath; this.$store.dispatch('fetchNotes', path) @@ -31,7 +45,16 @@ export default { class="loading"> +
    + +
diff --git a/app/assets/javascripts/notes/icons/emoji_slightly_smiling_face.svg b/app/assets/javascripts/notes/icons/emoji_slightly_smiling_face.svg new file mode 100644 index 00000000000..56dbad91554 --- /dev/null +++ b/app/assets/javascripts/notes/icons/emoji_slightly_smiling_face.svg @@ -0,0 +1 @@ + diff --git a/app/assets/javascripts/notes/icons/emoji_smile.svg b/app/assets/javascripts/notes/icons/emoji_smile.svg new file mode 100644 index 00000000000..ce645fee46f --- /dev/null +++ b/app/assets/javascripts/notes/icons/emoji_smile.svg @@ -0,0 +1 @@ + diff --git a/app/assets/javascripts/notes/icons/emoji_smiley.svg b/app/assets/javascripts/notes/icons/emoji_smiley.svg new file mode 100644 index 00000000000..ddfae50e566 --- /dev/null +++ b/app/assets/javascripts/notes/icons/emoji_smiley.svg @@ -0,0 +1 @@ + diff --git a/app/assets/javascripts/notes/stores/issue_notes_store.js b/app/assets/javascripts/notes/stores/issue_notes_store.js index 4b3c08e9ca8..8392f7bfab5 100644 --- a/app/assets/javascripts/notes/stores/issue_notes_store.js +++ b/app/assets/javascripts/notes/stores/issue_notes_store.js @@ -7,11 +7,20 @@ const state = { notes: [], }; -const getters = {}; +const getters = { + notes(storeState) { + return storeState.notes; + }, +}; const mutations = { - setNotes(vmState, notes) { - vmState.notes = notes; + setNotes(storeState, notes) { + storeState.notes = notes; + }, + toggleDiscussion(storeState, { discussionId }) { + const [ discussion ] = storeState.notes.filter((note) => note.id === discussionId); + + discussion.expanded = !discussion.expanded; }, }; @@ -24,7 +33,7 @@ const actions = { context.commit('setNotes', res); }) .catch(() => { - new Flash('Something went while fetching issue comments. Please try again.'); // eslint-disable-line + new Flash('Something went wrong while fetching issue comments. Please try again.'); // eslint-disable-line }); }, }; diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index aa04e490649..286b6f56cf9 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -453,6 +453,7 @@ color: $gray-darkest; display: block; margin: 16px 0 0; + font-size: 85%; .author_link { color: $gray-darkest; diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml index f0fcc414756..51049acf042 100644 --- a/app/views/shared/notes/_notes_with_form.html.haml +++ b/app/views/shared/notes/_notes_with_form.html.haml @@ -15,11 +15,11 @@ .timeline-content.timeline-content-form = render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete - elsif !current_user - .disabled-comment.text-center.prepend-top-default + .disabled-comment.text-center.prepend-top-default.js-disabled-comment Please - = link_to "register", new_session_path(:user, redirect_to_referer: 'yes') + = link_to "register", new_session_path(:user, redirect_to_referer: 'yes'), class: 'js-register-link' or - = link_to "sign in", new_session_path(:user, redirect_to_referer: 'yes') + = link_to "sign in", new_session_path(:user, redirect_to_referer: 'yes'), class: 'js-sign-in-link' to comment :javascript From 57ccfb9a4f88a652b02ca89d7a98326006a24227 Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Wed, 14 Jun 2017 05:13:03 +0300 Subject: [PATCH 007/243] Fix some ESLint errors. --- app/assets/javascripts/notes/components/issue_discussion.vue | 4 ++-- .../javascripts/notes/components/issue_note_edited_text.vue | 2 +- app/assets/javascripts/notes/components/issue_note_header.vue | 2 +- app/assets/javascripts/notes/components/issue_notes.vue | 2 +- app/assets/javascripts/notes/stores/issue_notes_store.js | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/notes/components/issue_discussion.vue b/app/assets/javascripts/notes/components/issue_discussion.vue index 21f1f721a05..236154f4c71 100644 --- a/app/assets/javascripts/notes/components/issue_discussion.vue +++ b/app/assets/javascripts/notes/components/issue_discussion.vue @@ -16,7 +16,7 @@ export default { return { registerLink: '#', signInLink: '#', - } + }; }, computed: { discussion() { @@ -43,7 +43,7 @@ export default { this.signInLink = signInLink.getAttribute('href'); } }, -} +};