From 938aa8bfe04a39a95a0dc7e63ddbac2eb016908f Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 26 May 2016 09:08:44 +0100 Subject: [PATCH 01/16] Added inline edit form to issue --- app/assets/javascripts/dispatcher.js.coffee | 1 + .../javascripts/issuable_edit.js.coffee | 69 +++++++++++++++++++ .../projects/issues/_branch_placeholder.haml | 2 + .../projects/issues/_inline_edit.html.haml | 24 +++++++ .../issues/_merge_requests_placeholder.haml | 2 + app/views/projects/issues/show.html.haml | 20 +----- 6 files changed, 101 insertions(+), 17 deletions(-) create mode 100644 app/assets/javascripts/issuable_edit.js.coffee create mode 100644 app/views/projects/issues/_branch_placeholder.haml create mode 100644 app/views/projects/issues/_inline_edit.html.haml create mode 100644 app/views/projects/issues/_merge_requests_placeholder.haml diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 74fd77cf7abc..fb75d26a2966 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -21,6 +21,7 @@ class Dispatcher shortcut_handler = new ShortcutsNavigation() when 'projects:issues:show' new Issue() + new IssuableEdit() shortcut_handler = new ShortcutsIssuable() new ZenMode() when 'projects:milestones:show', 'groups:milestones:show', 'dashboard:milestones:show' diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee new file mode 100644 index 000000000000..7af769edad5c --- /dev/null +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -0,0 +1,69 @@ +class @IssuableEdit + constructor: -> + @removeEventListeners() + @initEventListeners() + + new GLForm $('.js-issuable-inline-form') + + removeEventListeners: -> + $(document).off 'click', '.js-issuable-title' + $(document).off 'blur', '.js-issuable-edit-title' + $(document).off 'click', '.js-issuable-description' + $(document).off 'blur', '.js-task-list-field' + $(document).off 'click', '.js-issuable-title-save' + + initEventListeners: -> + # Title field + $(document).on 'click', '.js-issuable-title', @showTitleEdit + $(document).on 'blur', '.js-issuable-edit-title', @hideTitleEdit + $(document).on 'click', '.js-issuable-title-save', @saveTitle + + # Description field + $(document).on 'click', '.js-issuable-description', @showDescriptionEdit + $(document).on 'blur', '.js-task-list-field', @hideDescriptionEdit + + showTitleEdit: -> + $(this).addClass 'hidden' + $('.js-issuable-edit-title') + .removeClass 'hidden' + $('.js-issuable-title-field') + .focus() + + hideTitleEdit: (e) -> + if $(e.currentTarget).is ':not(.js-issuable-edit-title)' + $('.js-issuable-edit-title').addClass 'hidden' + $('.js-issuable-title').removeClass 'hidden' + + saveTitle: (e) => + e.preventDefault() + title = $('.js-issuable-title-field').val() + + # Hide the edit form + @hideTitleEdit(e) + + $('.js-issuable-title-loading').removeClass 'hidden' + @postData( + issue: + title: title + ).done (data) -> + $('.js-issuable-title').text data.title + $('.js-issuable-title-loading').addClass 'hidden' + + showDescriptionEdit: -> + $(this).addClass 'hidden' + $('.js-issuable-description-field') + .removeClass 'hidden' + $('.js-task-list-field') + .focus() + + hideDescriptionEdit: -> + $('.js-issuable-description-field').addClass 'hidden' + $('.js-issuable-description').removeClass 'hidden' + + postData: (data) -> + $.ajax( + url: $('.js-issuable-inline-form').attr('action') + type: 'PATCH' + dataType: 'json' + data: data + ) diff --git a/app/views/projects/issues/_branch_placeholder.haml b/app/views/projects/issues/_branch_placeholder.haml new file mode 100644 index 000000000000..976415e13f6b --- /dev/null +++ b/app/views/projects/issues/_branch_placeholder.haml @@ -0,0 +1,2 @@ +#related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, @issue) } } + // This element is filled in using JavaScript. diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/projects/issues/_inline_edit.html.haml new file mode 100644 index 000000000000..0a763d5ec28e --- /dev/null +++ b/app/views/projects/issues/_inline_edit.html.haml @@ -0,0 +1,24 @@ += form_for @issue, html: { class: 'detail-page-description content-block common-note-form js-issuable-inline-form' } do |f| + %h2.title + %span.js-issuable-title= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author + = icon('spinner spin', class: 'js-issuable-title-loading hidden') + .input-group.js-issuable-edit-title.hidden + = f.text_field :title, class: 'form-control js-issuable-title-field' + %span.input-group-btn + %button.btn.btn-success.js-issuable-title-save{ type: "submit" } + Save + - if @issue.description.present? + .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } + .wiki.js-issuable-description + = preserve do + = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) + .js-issuable-description-field.hidden + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do + = render 'projects/zen', f: f, attr: :description, + classes: 'note-textarea js-task-list-field', + placeholder: "Write a comment or drag your files here..." + = render 'projects/notes/hints' + = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') + + = render "merge_requests_placeholder" + = render "branch_placeholder" diff --git a/app/views/projects/issues/_merge_requests_placeholder.haml b/app/views/projects/issues/_merge_requests_placeholder.haml new file mode 100644 index 000000000000..082a68394007 --- /dev/null +++ b/app/views/projects/issues/_merge_requests_placeholder.haml @@ -0,0 +1,2 @@ +#merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } } + // This element is filled in using JavaScript. diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 9b6a97c0959f..5353870e6cb2 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -48,23 +48,9 @@ .issue-details.issuable-details - .detail-page-description.content-block - %h2.title - = markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author - - if @issue.description.present? - .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } - .wiki - = preserve do - = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) - %textarea.hidden.js-task-list-field - = @issue.description - = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') - - #merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } } - // This element is filled in using JavaScript. - - #related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, @issue) } } - // This element is filled in using JavaScript. + - if can?(current_user, :update_issue, @issue) + = render 'inline_edit' + - else .content-block.content-block-small = render 'new_branch' -- GitLab From 04706cf2ad47a0a47d0ca2c50db5c0dc7e0384bc Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 27 May 2016 08:57:00 +0100 Subject: [PATCH 02/16] Fixed issue with blur event --- app/assets/javascripts/issuable_edit.js.coffee | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index 7af769edad5c..a60fdb7c1340 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -30,13 +30,12 @@ class @IssuableEdit .focus() hideTitleEdit: (e) -> - if $(e.currentTarget).is ':not(.js-issuable-edit-title)' + unless e.relatedTarget? $('.js-issuable-edit-title').addClass 'hidden' $('.js-issuable-title').removeClass 'hidden' saveTitle: (e) => e.preventDefault() - title = $('.js-issuable-title-field').val() # Hide the edit form @hideTitleEdit(e) @@ -44,7 +43,7 @@ class @IssuableEdit $('.js-issuable-title-loading').removeClass 'hidden' @postData( issue: - title: title + title: $('.js-issuable-title-field').val() ).done (data) -> $('.js-issuable-title').text data.title $('.js-issuable-title-loading').addClass 'hidden' -- GitLab From 687a2958d51e3139f1013ca56e548ef9443a0d8b Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 27 May 2016 11:36:29 +0100 Subject: [PATCH 03/16] Returns the HTML in the JSON correctly --- .../javascripts/issuable_edit.js.coffee | 37 +++++++++---------- app/controllers/projects/issues_controller.rb | 14 ++++++- .../projects/issues/_inline_edit.html.haml | 15 +++++--- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index a60fdb7c1340..d7eab1c2d097 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -6,13 +6,18 @@ class @IssuableEdit new GLForm $('.js-issuable-inline-form') removeEventListeners: -> + $(document).off 'ajax:success', '.js-issuable-inline-form' $(document).off 'click', '.js-issuable-title' $(document).off 'blur', '.js-issuable-edit-title' $(document).off 'click', '.js-issuable-description' $(document).off 'blur', '.js-task-list-field' $(document).off 'click', '.js-issuable-title-save' + $(document).off 'click', '.js-issuable-description-cancel' + $(document).off 'click', '.js-issuable-description-save' initEventListeners: -> + $(document).on 'ajax:success', '.js-issuable-inline-form', @afterSave + # Title field $(document).on 'click', '.js-issuable-title', @showTitleEdit $(document).on 'blur', '.js-issuable-edit-title', @hideTitleEdit @@ -20,7 +25,8 @@ class @IssuableEdit # Description field $(document).on 'click', '.js-issuable-description', @showDescriptionEdit - $(document).on 'blur', '.js-task-list-field', @hideDescriptionEdit + $(document).on 'click', '.js-issuable-description-cancel', @hideDescriptionEdit + $(document).on 'click', '.js-issuable-description-save', @saveDescription showTitleEdit: -> $(this).addClass 'hidden' @@ -35,18 +41,11 @@ class @IssuableEdit $('.js-issuable-title').removeClass 'hidden' saveTitle: (e) => - e.preventDefault() - - # Hide the edit form @hideTitleEdit(e) - $('.js-issuable-title-loading').removeClass 'hidden' - @postData( - issue: - title: $('.js-issuable-title-field').val() - ).done (data) -> - $('.js-issuable-title').text data.title - $('.js-issuable-title-loading').addClass 'hidden' + + saveDescription: (e) => + @hideDescriptionEdit(e) showDescriptionEdit: -> $(this).addClass 'hidden' @@ -55,14 +54,14 @@ class @IssuableEdit $('.js-task-list-field') .focus() - hideDescriptionEdit: -> + hideDescriptionEdit: (e) -> $('.js-issuable-description-field').addClass 'hidden' $('.js-issuable-description').removeClass 'hidden' - postData: (data) -> - $.ajax( - url: $('.js-issuable-inline-form').attr('action') - type: 'PATCH' - dataType: 'json' - data: data - ) + afterSave: (e, data) -> + $('.js-issuable-title-loading').addClass 'hidden' + + # Update the HTML + # We need HTML returned so that the markdown can be correctly created on server side + $('.js-issuable-title').html data.title + $('.js-issuable-description').html data.description diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index f7ada5cfee43..d6fad9e43f4d 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -116,7 +116,19 @@ def update end format.json do - render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) + if params[:inline].nil? + render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) + else + ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user) + ext.analyze(@issue.title) + ext.analyze(@issue.description) + + render json: { + title: view_context.markdown(@issue.title, pipeline: :single_line), + description: view_context.markdown(@issue.description), + updated_at: @issue.updated_at, + }.to_json + end end end diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/projects/issues/_inline_edit.html.haml index 0a763d5ec28e..8725f94e5049 100644 --- a/app/views/projects/issues/_inline_edit.html.haml +++ b/app/views/projects/issues/_inline_edit.html.haml @@ -1,12 +1,12 @@ -= form_for @issue, html: { class: 'detail-page-description content-block common-note-form js-issuable-inline-form' } do |f| += form_for @issue, remote: true, html: { class: 'detail-page-description content-block common-note-form js-issuable-inline-form', data: { type: "json" } } do |f| + = hidden_field_tag :inline, true %h2.title %span.js-issuable-title= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author = icon('spinner spin', class: 'js-issuable-title-loading hidden') - .input-group.js-issuable-edit-title.hidden + .js-issuable-edit-title.hidden = f.text_field :title, class: 'form-control js-issuable-title-field' - %span.input-group-btn - %button.btn.btn-success.js-issuable-title-save{ type: "submit" } - Save + %button.btn.btn-success.js-issuable-title-save{ type: "submit" } + Save - if @issue.description.present? .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } .wiki.js-issuable-description @@ -18,6 +18,11 @@ classes: 'note-textarea js-task-list-field', placeholder: "Write a comment or drag your files here..." = render 'projects/notes/hints' + .prepend-top-10.append-bottom-10 + %button.btn.btn-success.js-issuable-description-save{ type: "submit" } + Save + %button.btn.btn-default.pull-right.js-issuable-description-cancel{ type: "button" } + Cancel = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') = render "merge_requests_placeholder" -- GitLab From 8caec053dd6a126e45698480ceb05853c266663e Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 27 May 2016 12:52:37 +0100 Subject: [PATCH 04/16] Cache jquery selectors --- .../javascripts/issuable_edit.js.coffee | 65 +++++++++++-------- app/assets/stylesheets/pages/issuable.scss | 11 ++++ .../projects/issues/_inline_edit.html.haml | 11 ++-- 3 files changed, 57 insertions(+), 30 deletions(-) diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index d7eab1c2d097..89b989e76580 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -1,9 +1,24 @@ class @IssuableEdit constructor: -> + @getElements() @removeEventListeners() @initEventListeners() - new GLForm $('.js-issuable-inline-form') + new GLForm(@elements.form) + + getElements: -> + @elements = + form: $('.js-issuable-inline-form') + title: + element: $('.js-issuable-title') + field: $('.js-issuable-title-field') + fieldset: $('.js-issuable-edit-title') + loading: $('.js-issuable-title-loading') + description: + element: $('.js-issuable-description') + field: $('.js-task-list-field') + fieldset: $('.js-issuable-description-field') + loading: $('.js-issuable-title-loading') removeEventListeners: -> $(document).off 'ajax:success', '.js-issuable-inline-form' @@ -12,56 +27,54 @@ class @IssuableEdit $(document).off 'click', '.js-issuable-description' $(document).off 'blur', '.js-task-list-field' $(document).off 'click', '.js-issuable-title-save' - $(document).off 'click', '.js-issuable-description-cancel' + $(document).off 'click', '.js-issuable-edit-cancel' $(document).off 'click', '.js-issuable-description-save' initEventListeners: -> $(document).on 'ajax:success', '.js-issuable-inline-form', @afterSave + $(document).on 'click', '.js-issuable-edit-cancel', @hideFields # Title field $(document).on 'click', '.js-issuable-title', @showTitleEdit - $(document).on 'blur', '.js-issuable-edit-title', @hideTitleEdit $(document).on 'click', '.js-issuable-title-save', @saveTitle # Description field $(document).on 'click', '.js-issuable-description', @showDescriptionEdit - $(document).on 'click', '.js-issuable-description-cancel', @hideDescriptionEdit $(document).on 'click', '.js-issuable-description-save', @saveDescription - showTitleEdit: -> - $(this).addClass 'hidden' - $('.js-issuable-edit-title') - .removeClass 'hidden' - $('.js-issuable-title-field') - .focus() + hideFields: (e) => + @hideTitleEdit(e) + @hideDescriptionEdit(e) + + showTitleEdit: => + @elements.title.element.addClass 'hidden' + @elements.title.fieldset.removeClass 'hidden' + @elements.title.field.focus() hideTitleEdit: (e) -> - unless e.relatedTarget? - $('.js-issuable-edit-title').addClass 'hidden' - $('.js-issuable-title').removeClass 'hidden' + @elements.title.fieldset.addClass 'hidden' + @elements.title.element.removeClass 'hidden' saveTitle: (e) => - @hideTitleEdit(e) - $('.js-issuable-title-loading').removeClass 'hidden' + @hideTitleEdit() + @elements.title.loading.removeClass 'hidden' saveDescription: (e) => @hideDescriptionEdit(e) showDescriptionEdit: -> - $(this).addClass 'hidden' - $('.js-issuable-description-field') - .removeClass 'hidden' - $('.js-task-list-field') - .focus() + @elements.description.element.addClass 'hidden' + @elements.description.fieldset.removeClass 'hidden' + @elements.description.field.focus() hideDescriptionEdit: (e) -> - $('.js-issuable-description-field').addClass 'hidden' - $('.js-issuable-description').removeClass 'hidden' + @elements.description.fieldset.addClass 'hidden' + @elements.description.element.removeClass 'hidden' - afterSave: (e, data) -> - $('.js-issuable-title-loading').addClass 'hidden' + afterSave: (e, data) => + @elements.title.loading.addClass 'hidden' # Update the HTML # We need HTML returned so that the markdown can be correctly created on server side - $('.js-issuable-title').html data.title - $('.js-issuable-description').html data.description + @elements.title.element.html data.title + @elements.description.element.html data.description diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 542fa244689a..060b795d0e6f 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -394,3 +394,14 @@ display: inline-block; line-height: 18px; } + +.issuable-title-edit { + position: relative; + padding-right: 127px; +} + +.issuable-title-edit-buttons { + position: absolute; + right: 0; + top: 0; +} diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/projects/issues/_inline_edit.html.haml index 8725f94e5049..5a8cf4d78294 100644 --- a/app/views/projects/issues/_inline_edit.html.haml +++ b/app/views/projects/issues/_inline_edit.html.haml @@ -3,10 +3,13 @@ %h2.title %span.js-issuable-title= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author = icon('spinner spin', class: 'js-issuable-title-loading hidden') - .js-issuable-edit-title.hidden + .issuable-title-edit.js-issuable-edit-title.hidden = f.text_field :title, class: 'form-control js-issuable-title-field' - %button.btn.btn-success.js-issuable-title-save{ type: "submit" } - Save + .issuable-title-edit-buttons + %button.btn.btn-success.js-issuable-title-save{ type: "submit" } + Save + %button.btn.btn-default.js-issuable-edit-cancel{ type: "button" } + Cancel - if @issue.description.present? .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } .wiki.js-issuable-description @@ -21,7 +24,7 @@ .prepend-top-10.append-bottom-10 %button.btn.btn-success.js-issuable-description-save{ type: "submit" } Save - %button.btn.btn-default.pull-right.js-issuable-description-cancel{ type: "button" } + %button.btn.btn-default.pull-right.js-issuable-edit-cancel{ type: "button" } Cancel = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') -- GitLab From fe9fbe8f09bd9d85480ade8139a197394564e055 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 31 May 2016 16:56:09 +0100 Subject: [PATCH 05/16] Added inline editing to merge requests --- app/assets/javascripts/dispatcher.js.coffee | 1 + .../javascripts/issuable_edit.js.coffee | 6 +++- app/assets/stylesheets/pages/detail_page.scss | 4 +++ .../projects/merge_requests_controller.rb | 14 ++++++++- app/views/projects/issues/show.html.haml | 13 +++++++++ .../show/_inline_edit.html.haml | 29 +++++++++++++++++++ .../merge_requests/show/_mr_box.html.haml | 14 ++++----- 7 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 app/views/projects/merge_requests/show/_inline_edit.html.haml diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index fb75d26a2966..e8a98e2b9033 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -56,6 +56,7 @@ class Dispatcher shortcut_handler = new ShortcutsIssuable(true) new ZenMode() new MergedButtons() + new IssuableEdit() when 'projects:merge_requests:commits', 'projects:merge_requests:builds' new MergedButtons() when "projects:merge_requests:diffs" diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index 89b989e76580..bcf70fee914d 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -61,8 +61,9 @@ class @IssuableEdit saveDescription: (e) => @hideDescriptionEdit(e) + @elements.description.element.addClass 'is-loading' - showDescriptionEdit: -> + showDescriptionEdit: => @elements.description.element.addClass 'hidden' @elements.description.fieldset.removeClass 'hidden' @elements.description.field.focus() @@ -72,7 +73,10 @@ class @IssuableEdit @elements.description.element.removeClass 'hidden' afterSave: (e, data) => + $('.js-issuable-inline-form [type="submit"]').enable() + @elements.title.loading.addClass 'hidden' + @elements.description.element.removeClass 'is-loading' # Update the HTML # We need HTML returned so that the markdown can be correctly created on server side diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index 1b389d83525d..c3b3892f8427 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -33,6 +33,10 @@ margin-bottom: 0; } } + + .is-loading { + opacity: .5; + } } .wiki { diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 2deb79597001..1de23781703f 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -190,7 +190,19 @@ def update @merge_request.target_project, @merge_request]) end format.json do - render json: @merge_request.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) + if params[:inline].nil? + render json: @merge_request.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) + else + ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user) + ext.analyze(@merge_request.title) + ext.analyze(@merge_request.description) + + render json: { + title: view_context.markdown(@merge_request.title, pipeline: :single_line), + description: view_context.markdown(@merge_request.description), + updated_at: @merge_request.updated_at, + }.to_json + end end end else diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 5353870e6cb2..9f7f0e0920d3 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -51,6 +51,19 @@ - if can?(current_user, :update_issue, @issue) = render 'inline_edit' - else + .detail-page-description.content-block + %h2.title + = markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author + - if @issue.description.present? + .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } + .wiki + = preserve do + = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) + %textarea.hidden.js-task-list-field + = @issue.description + = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') + = render "merge_requests_placeholder" + = render "branch_placeholder" .content-block.content-block-small = render 'new_branch' diff --git a/app/views/projects/merge_requests/show/_inline_edit.html.haml b/app/views/projects/merge_requests/show/_inline_edit.html.haml new file mode 100644 index 000000000000..8a3c7f89dd69 --- /dev/null +++ b/app/views/projects/merge_requests/show/_inline_edit.html.haml @@ -0,0 +1,29 @@ += form_for @merge_request, remote: true, html: { class: 'detail-page-description content-block common-note-form js-issuable-inline-form', data: { type: "json" } } do |f| + = hidden_field_tag :inline, true + %h2.title + %span.js-issuable-title= markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author + = icon('spinner spin', class: 'js-issuable-title-loading hidden') + .issuable-title-edit.js-issuable-edit-title.hidden + = f.text_field :title, class: 'form-control js-issuable-title-field' + .issuable-title-edit-buttons + %button.btn.btn-success.js-issuable-title-save{ type: "submit" } + Save + %button.btn.btn-default.js-issuable-edit-cancel{ type: "button" } + Cancel + - if @merge_request.description.present? + .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} + .wiki.js-issuable-description + = preserve do + = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author) + .js-issuable-description-field.hidden + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do + = render 'projects/zen', f: f, attr: :description, + classes: 'note-textarea js-task-list-field', + placeholder: "Write a comment or drag your files here..." + = render 'projects/notes/hints' + .prepend-top-10.append-bottom-10 + %button.btn.btn-success.js-issuable-description-save{ type: "submit" } + Save + %button.btn.btn-default.pull-right.js-issuable-edit-cancel{ type: "button" } + Cancel + = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index ebf18f6ac859..01a8db84456d 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -1,8 +1,9 @@ -.detail-page-description.content-block - %h2.title - = markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author - - %div +- if can?(current_user, :update_merge_request, @merge_request) + = render "projects/merge_requests/show/inline_edit" +- else + .detail-page-description.content-block + %h2.title + = markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author - if @merge_request.description.present? .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} .wiki @@ -10,5 +11,4 @@ = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author) %textarea.hidden.js-task-list-field = @merge_request.description - - = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') + = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') -- GitLab From 4d88e33935506e1deeafe605e9e7738fc56381dc Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 1 Jun 2016 10:35:08 +0100 Subject: [PATCH 06/16] Added tests --- spec/features/issues/inline_edit_spec.rb | 66 ++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 spec/features/issues/inline_edit_spec.rb diff --git a/spec/features/issues/inline_edit_spec.rb b/spec/features/issues/inline_edit_spec.rb new file mode 100644 index 000000000000..7a24c04ca5ef --- /dev/null +++ b/spec/features/issues/inline_edit_spec.rb @@ -0,0 +1,66 @@ +require 'rails_helper' + +describe 'Issue inline editing', feature: true, js: true do + let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) } + let(:user) { create(:user) } + let(:issue) { create(:issue, project: project, description: 'description') } + + context 'user is allowed to edit issue' do + before do + project.team << [user, :master] + login_as(user) + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'should allow user to update title' do + find('.js-issuable-title').click + expect(page).to have_selector('.js-issuable-edit-title', visible: true) + fill_in 'issue_title', with: 'test' + click_button 'Save' + + page.within '.issuable-details' do + expect(page).to have_content 'test' + end + end + + it 'should hide title field' do + find('.js-issuable-title').click + expect(page).to have_selector('.js-issuable-edit-title', visible: true) + click_button 'Cancel' + expect(page).to have_selector('.js-issuable-edit-title', visible: false) + end + + it 'should allow user to update description' do + find('.js-issuable-description').click + expect(page).to have_selector('.js-issuable-description-field', visible: true) + fill_in 'issue_description', with: 'test' + click_button 'Save' + + page.within '.issuable-details' do + expect(page).to have_content 'test' + end + end + + it 'should hide description field' do + find('.js-issuable-description').click + expect(page).to have_selector('.js-issuable-description-field', visible: true) + click_button 'Cancel' + expect(page).to have_selector('.js-issuable-description-field', visible: false) + end + end + + context 'user is not allowed to edit issue' do + before do + login_as(user) + visit namespace_project_issue_path(project.namespace, project, issue) + end + + it 'should not allow editing of title' do + expect(page).not_to have_selector('.js-issuable-title', visible: false) + end + + it 'should not allow editing of description' do + expect(page).not_to have_selector('.js-issuable-description', visible: false) + end + end +end -- GitLab From f99a3a86b9097903f8d3650c06e9116e892f2a80 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 1 Jun 2016 10:42:00 +0100 Subject: [PATCH 07/16] Allowed quick submit Fixed issue with tasklist not working --- app/assets/javascripts/issuable_edit.js.coffee | 14 ++++++++++---- app/views/projects/issues/_inline_edit.html.haml | 2 +- .../merge_requests/show/_inline_edit.html.haml | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index bcf70fee914d..7ebb3363b13e 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -63,10 +63,11 @@ class @IssuableEdit @hideDescriptionEdit(e) @elements.description.element.addClass 'is-loading' - showDescriptionEdit: => - @elements.description.element.addClass 'hidden' - @elements.description.fieldset.removeClass 'hidden' - @elements.description.field.focus() + showDescriptionEdit: (e) => + if $(e.target).is(':not(input,a)') + @elements.description.element.addClass 'hidden' + @elements.description.fieldset.removeClass 'hidden' + @elements.description.field.focus() hideDescriptionEdit: (e) -> @elements.description.fieldset.addClass 'hidden' @@ -75,6 +76,9 @@ class @IssuableEdit afterSave: (e, data) => $('.js-issuable-inline-form [type="submit"]').enable() + @hideTitleEdit() + @hideDescriptionEdit(e) + @elements.title.loading.addClass 'hidden' @elements.description.element.removeClass 'is-loading' @@ -82,3 +86,5 @@ class @IssuableEdit # We need HTML returned so that the markdown can be correctly created on server side @elements.title.element.html data.title @elements.description.element.html data.description + + $('.detail-page-description .js-task-list-container').taskList('enable') diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/projects/issues/_inline_edit.html.haml index 5a8cf4d78294..809071820a1d 100644 --- a/app/views/projects/issues/_inline_edit.html.haml +++ b/app/views/projects/issues/_inline_edit.html.haml @@ -1,4 +1,4 @@ -= form_for @issue, remote: true, html: { class: 'detail-page-description content-block common-note-form js-issuable-inline-form', data: { type: "json" } } do |f| += form_for @issue, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| = hidden_field_tag :inline, true %h2.title %span.js-issuable-title= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author diff --git a/app/views/projects/merge_requests/show/_inline_edit.html.haml b/app/views/projects/merge_requests/show/_inline_edit.html.haml index 8a3c7f89dd69..78127bba285f 100644 --- a/app/views/projects/merge_requests/show/_inline_edit.html.haml +++ b/app/views/projects/merge_requests/show/_inline_edit.html.haml @@ -1,4 +1,4 @@ -= form_for @merge_request, remote: true, html: { class: 'detail-page-description content-block common-note-form js-issuable-inline-form', data: { type: "json" } } do |f| += form_for @merge_request, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| = hidden_field_tag :inline, true %h2.title %span.js-issuable-title= markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author -- GitLab From 2fdfe412021f9925531564519075cdd789e59a42 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 1 Jun 2016 10:42:24 +0100 Subject: [PATCH 08/16] CHANGELOG --- CHANGELOG | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 6b24b2c5b327..685217620c8a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -399,6 +399,12 @@ v 8.8.3 - Fix serious performance bug with rendering Markdown with InlineDiffFilter. !4392 - Fix missing number on generated ordered list element. !4437 - Prevent disclosure of notes on confidential issues in search results. + - Fix incorrect links on pipeline page when merge request created from fork + - Fix gitlab importer failing to import new projects due to missing credentials + - Fix import URL migration not rescuing with the correct Error + - In search results, only show notes on confidential issues that the user has access to + - Fix health check access token changing due to old application settings being used + - Inline editing of issue & merge request title and description v 8.8.2 - Added remove due date button. !4209 -- GitLab From b85bc58e8b2acf0c4a3717d7f82020f4f4479028 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 2 Jun 2016 12:30:35 +0100 Subject: [PATCH 09/16] Fixed tests --- app/controllers/projects/issues_controller.rb | 2 +- app/controllers/projects/merge_requests_controller.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index d6fad9e43f4d..2a8d2dcaa056 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -119,7 +119,7 @@ def update if params[:inline].nil? render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) else - ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user) + ext = Gitlab::ReferenceExtractor.new(@project, current_user) ext.analyze(@issue.title) ext.analyze(@issue.description) diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 1de23781703f..2a50be546d69 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -193,7 +193,7 @@ def update if params[:inline].nil? render json: @merge_request.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) else - ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user) + ext = Gitlab::ReferenceExtractor.new(@project, current_user) ext.analyze(@merge_request.title) ext.analyze(@merge_request.description) -- GitLab From c38ba2ad858f27d312bd6795af93318489faea29 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Wed, 8 Jun 2016 09:46:58 +0100 Subject: [PATCH 10/16] Added tooltip to show fields are editable Correclty removes all added event listeners --- .../javascripts/issuable_edit.js.coffee | 10 ++++---- app/assets/stylesheets/pages/issuable.scss | 23 +++++++++++++++++++ .../projects/issues/_inline_edit.html.haml | 4 ++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index 7ebb3363b13e..336ff23a6b06 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -22,12 +22,12 @@ class @IssuableEdit removeEventListeners: -> $(document).off 'ajax:success', '.js-issuable-inline-form' + $(document).off 'click', '.js-issuable-edit-cancel' + $(document).off 'click', '.js-issuable-title' - $(document).off 'blur', '.js-issuable-edit-title' - $(document).off 'click', '.js-issuable-description' - $(document).off 'blur', '.js-task-list-field' $(document).off 'click', '.js-issuable-title-save' - $(document).off 'click', '.js-issuable-edit-cancel' + + $(document).off 'click', '.js-issuable-description' $(document).off 'click', '.js-issuable-description-save' initEventListeners: -> @@ -78,7 +78,7 @@ class @IssuableEdit @hideTitleEdit() @hideDescriptionEdit(e) - + @elements.title.loading.addClass 'hidden' @elements.description.element.removeClass 'is-loading' diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 060b795d0e6f..a6175ab8e1c3 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -405,3 +405,26 @@ right: 0; top: 0; } + +.inline-edit-box { + position: relative; + + &::before { + content: ''; + display: none; + position: absolute; + top: -3px; + right: -8px; + bottom: -3px; + left: -8px; + border: 1px solid $gray-dark; + border-radius: $border-radius-default; + pointer-events: none; + } + + &:hover { + &::before { + display: block; + } + } +} diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/projects/issues/_inline_edit.html.haml index 809071820a1d..b3f4a2080c4b 100644 --- a/app/views/projects/issues/_inline_edit.html.haml +++ b/app/views/projects/issues/_inline_edit.html.haml @@ -1,7 +1,7 @@ = form_for @issue, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| = hidden_field_tag :inline, true %h2.title - %span.js-issuable-title= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author + %span.inline-edit-box.has-tooltip.js-issuable-title{ title: "Edit title" }= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author = icon('spinner spin', class: 'js-issuable-title-loading hidden') .issuable-title-edit.js-issuable-edit-title.hidden = f.text_field :title, class: 'form-control js-issuable-title-field' @@ -12,7 +12,7 @@ Cancel - if @issue.description.present? .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } - .wiki.js-issuable-description + .wiki.inline-edit-box.has-tooltip.js-issuable-description{ title: "Edit description" } = preserve do = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) .js-issuable-description-field.hidden -- GitLab From 7d793af7b83b44394439cf4ae2efef7367b6e8a0 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 9 Jun 2016 10:53:34 +0100 Subject: [PATCH 11/16] Only shows one editable field at a time --- app/assets/javascripts/issuable_edit.js.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index 336ff23a6b06..746c7cdca98b 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -47,6 +47,7 @@ class @IssuableEdit @hideDescriptionEdit(e) showTitleEdit: => + @hideDescriptionEdit() @elements.title.element.addClass 'hidden' @elements.title.fieldset.removeClass 'hidden' @elements.title.field.focus() @@ -65,11 +66,12 @@ class @IssuableEdit showDescriptionEdit: (e) => if $(e.target).is(':not(input,a)') + @hideTitleEdit(e) @elements.description.element.addClass 'hidden' @elements.description.fieldset.removeClass 'hidden' @elements.description.field.focus() - hideDescriptionEdit: (e) -> + hideDescriptionEdit: -> @elements.description.fieldset.addClass 'hidden' @elements.description.element.removeClass 'hidden' -- GitLab From 7ef53317d8c425d18c85ed6c37f38c90085609f6 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 9 Jun 2016 13:18:51 +0100 Subject: [PATCH 12/16] Changed editable indicator --- app/assets/stylesheets/pages/issuable.scss | 22 ++++++------------- .../projects/issues/_inline_edit.html.haml | 4 ++-- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index a6175ab8e1c3..f0be5f26b5d4 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -409,22 +409,14 @@ .inline-edit-box { position: relative; - &::before { - content: ''; - display: none; - position: absolute; - top: -3px; - right: -8px; - bottom: -3px; - left: -8px; - border: 1px solid $gray-dark; - border-radius: $border-radius-default; - pointer-events: none; - } - &:hover { - &::before { - display: block; + &::after { + content: ''; + position: absolute; + right: 0; + bottom: -2px; + left: 0; + border-top: 2px dashed $focus-border-color; } } } diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/projects/issues/_inline_edit.html.haml index b3f4a2080c4b..4226ab704378 100644 --- a/app/views/projects/issues/_inline_edit.html.haml +++ b/app/views/projects/issues/_inline_edit.html.haml @@ -1,7 +1,7 @@ = form_for @issue, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| = hidden_field_tag :inline, true %h2.title - %span.inline-edit-box.has-tooltip.js-issuable-title{ title: "Edit title" }= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author + %span.inline-edit-box.js-issuable-title= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author = icon('spinner spin', class: 'js-issuable-title-loading hidden') .issuable-title-edit.js-issuable-edit-title.hidden = f.text_field :title, class: 'form-control js-issuable-title-field' @@ -12,7 +12,7 @@ Cancel - if @issue.description.present? .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } - .wiki.inline-edit-box.has-tooltip.js-issuable-description{ title: "Edit description" } + .wiki.inline-edit-box.js-issuable-description = preserve do = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) .js-issuable-description-field.hidden -- GitLab From fc26e618a65a1b082f8a0a0f0a3866d5b653ecaf Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 10 Jun 2016 16:24:06 +0100 Subject: [PATCH 13/16] Updated design when hovering over editable text --- app/assets/stylesheets/pages/issuable.scss | 19 +++++++++++++++++++ .../projects/issues/_inline_edit.html.haml | 2 +- .../show/_inline_edit.html.haml | 4 ++-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index f0be5f26b5d4..9c656da7926c 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -406,6 +406,12 @@ top: 0; } +.issuable-title-edit { + .form-control { + font-size: inherit; + } +} + .inline-edit-box { position: relative; @@ -420,3 +426,16 @@ } } } + +.inline-edit-description-box { + &:hover { + &::before { + content: ''; + position: absolute; + right: 0; + top: -2px; + left: 0; + border-top: 2px dashed $focus-border-color; + } + } +} diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/projects/issues/_inline_edit.html.haml index 4226ab704378..ff763a221ce4 100644 --- a/app/views/projects/issues/_inline_edit.html.haml +++ b/app/views/projects/issues/_inline_edit.html.haml @@ -12,7 +12,7 @@ Cancel - if @issue.description.present? .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } - .wiki.inline-edit-box.js-issuable-description + .wiki.inline-edit-box.inline-edit-description-box.js-issuable-description = preserve do = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) .js-issuable-description-field.hidden diff --git a/app/views/projects/merge_requests/show/_inline_edit.html.haml b/app/views/projects/merge_requests/show/_inline_edit.html.haml index 78127bba285f..b759deadb7d5 100644 --- a/app/views/projects/merge_requests/show/_inline_edit.html.haml +++ b/app/views/projects/merge_requests/show/_inline_edit.html.haml @@ -1,7 +1,7 @@ = form_for @merge_request, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| = hidden_field_tag :inline, true %h2.title - %span.js-issuable-title= markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author + %span.inline-edit-box.js-issuable-title= markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author = icon('spinner spin', class: 'js-issuable-title-loading hidden') .issuable-title-edit.js-issuable-edit-title.hidden = f.text_field :title, class: 'form-control js-issuable-title-field' @@ -12,7 +12,7 @@ Cancel - if @merge_request.description.present? .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} - .wiki.js-issuable-description + .wiki.inline-edit-box.inline-edit-description-box.js-issuable-description = preserve do = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author) .js-issuable-description-field.hidden -- GitLab From e7a6104b0d79c01fedae3448e19dc95646d59f2a Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Thu, 16 Jun 2016 09:48:21 +0100 Subject: [PATCH 14/16] Moved inline edit to shared file --- CHANGELOG | 7 +---- .../projects/issues/_branch_placeholder.haml | 2 -- .../issues/_merge_requests_placeholder.haml | 2 -- app/views/projects/issues/show.html.haml | 6 ++-- .../show/_inline_edit.html.haml | 29 ------------------- .../merge_requests/show/_mr_box.html.haml | 2 +- .../issuable}/_inline_edit.html.haml | 17 ++++++----- 7 files changed, 14 insertions(+), 51 deletions(-) delete mode 100644 app/views/projects/issues/_branch_placeholder.haml delete mode 100644 app/views/projects/issues/_merge_requests_placeholder.haml delete mode 100644 app/views/projects/merge_requests/show/_inline_edit.html.haml rename app/views/{projects/issues => shared/issuable}/_inline_edit.html.haml (61%) diff --git a/CHANGELOG b/CHANGELOG index 685217620c8a..913df296590e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -328,6 +328,7 @@ v 8.9.0 - Remove deprecated issues_tracker and issues_tracker_id from project model - Allow users to create confidential issues in private projects - Measure CPU time for instrumented methods + - Inline editing of issue & merge request title and description - Instrument private methods and private instance methods by default instead just public methods - Only show notes through JSON on confidential issues that the user has access to - Updated the allocations Gem to version 1.0.5 @@ -399,12 +400,6 @@ v 8.8.3 - Fix serious performance bug with rendering Markdown with InlineDiffFilter. !4392 - Fix missing number on generated ordered list element. !4437 - Prevent disclosure of notes on confidential issues in search results. - - Fix incorrect links on pipeline page when merge request created from fork - - Fix gitlab importer failing to import new projects due to missing credentials - - Fix import URL migration not rescuing with the correct Error - - In search results, only show notes on confidential issues that the user has access to - - Fix health check access token changing due to old application settings being used - - Inline editing of issue & merge request title and description v 8.8.2 - Added remove due date button. !4209 diff --git a/app/views/projects/issues/_branch_placeholder.haml b/app/views/projects/issues/_branch_placeholder.haml deleted file mode 100644 index 976415e13f6b..000000000000 --- a/app/views/projects/issues/_branch_placeholder.haml +++ /dev/null @@ -1,2 +0,0 @@ -#related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, @issue) } } - // This element is filled in using JavaScript. diff --git a/app/views/projects/issues/_merge_requests_placeholder.haml b/app/views/projects/issues/_merge_requests_placeholder.haml deleted file mode 100644 index 082a68394007..000000000000 --- a/app/views/projects/issues/_merge_requests_placeholder.haml +++ /dev/null @@ -1,2 +0,0 @@ -#merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } } - // This element is filled in using JavaScript. diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 9f7f0e0920d3..829bda011990 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -49,7 +49,7 @@ .issue-details.issuable-details - if can?(current_user, :update_issue, @issue) - = render 'inline_edit' + = render 'shared/issuable/inline_edit', issuable: @issue - else .detail-page-description.content-block %h2.title @@ -62,8 +62,8 @@ %textarea.hidden.js-task-list-field = @issue.description = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') - = render "merge_requests_placeholder" - = render "branch_placeholder" + #merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } } + #related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, @issue) } } .content-block.content-block-small = render 'new_branch' diff --git a/app/views/projects/merge_requests/show/_inline_edit.html.haml b/app/views/projects/merge_requests/show/_inline_edit.html.haml deleted file mode 100644 index b759deadb7d5..000000000000 --- a/app/views/projects/merge_requests/show/_inline_edit.html.haml +++ /dev/null @@ -1,29 +0,0 @@ -= form_for @merge_request, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| - = hidden_field_tag :inline, true - %h2.title - %span.inline-edit-box.js-issuable-title= markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author - = icon('spinner spin', class: 'js-issuable-title-loading hidden') - .issuable-title-edit.js-issuable-edit-title.hidden - = f.text_field :title, class: 'form-control js-issuable-title-field' - .issuable-title-edit-buttons - %button.btn.btn-success.js-issuable-title-save{ type: "submit" } - Save - %button.btn.btn-default.js-issuable-edit-cancel{ type: "button" } - Cancel - - if @merge_request.description.present? - .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} - .wiki.inline-edit-box.inline-edit-description-box.js-issuable-description - = preserve do - = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author) - .js-issuable-description-field.hidden - = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do - = render 'projects/zen', f: f, attr: :description, - classes: 'note-textarea js-task-list-field', - placeholder: "Write a comment or drag your files here..." - = render 'projects/notes/hints' - .prepend-top-10.append-bottom-10 - %button.btn.btn-success.js-issuable-description-save{ type: "submit" } - Save - %button.btn.btn-default.pull-right.js-issuable-edit-cancel{ type: "button" } - Cancel - = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index 01a8db84456d..32dc6e59bc62 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -1,5 +1,5 @@ - if can?(current_user, :update_merge_request, @merge_request) - = render "projects/merge_requests/show/inline_edit" + = render 'shared/issuable/inline_edit', issuable: @merge_request - else .detail-page-description.content-block %h2.title diff --git a/app/views/projects/issues/_inline_edit.html.haml b/app/views/shared/issuable/_inline_edit.html.haml similarity index 61% rename from app/views/projects/issues/_inline_edit.html.haml rename to app/views/shared/issuable/_inline_edit.html.haml index ff763a221ce4..5c3bf11be318 100644 --- a/app/views/projects/issues/_inline_edit.html.haml +++ b/app/views/shared/issuable/_inline_edit.html.haml @@ -1,7 +1,7 @@ -= form_for @issue, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| += form_for issuable, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| = hidden_field_tag :inline, true %h2.title - %span.inline-edit-box.js-issuable-title= markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author + %span.inline-edit-box.js-issuable-title= markdown escape_once(issuable.title), pipeline: :single_line, author: issuable.author = icon('spinner spin', class: 'js-issuable-title-loading hidden') .issuable-title-edit.js-issuable-edit-title.hidden = f.text_field :title, class: 'form-control js-issuable-title-field' @@ -10,11 +10,11 @@ Save %button.btn.btn-default.js-issuable-edit-cancel{ type: "button" } Cancel - - if @issue.description.present? - .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } + - if issuable.description.present? + .description{ class: 'js-task-list-container' } .wiki.inline-edit-box.inline-edit-description-box.js-issuable-description = preserve do - = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) + = markdown(issuable.description, cache_key: [issuable, "description"], author: issuable.author) .js-issuable-description-field.hidden = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do = render 'projects/zen', f: f, attr: :description, @@ -26,7 +26,8 @@ Save %button.btn.btn-default.pull-right.js-issuable-edit-cancel{ type: "button" } Cancel - = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') + = edited_time_ago_with_tooltip(issuable, placement: 'bottom', html_class: 'issue_edited_ago') - = render "merge_requests_placeholder" - = render "branch_placeholder" + - if issuable.is_a? Issue + #merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, issuable) } } + #related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, issuable) } } -- GitLab From 82f99bbbe24f8f422e419125635d79e6257723aa Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Tue, 12 Jul 2016 09:54:05 +0100 Subject: [PATCH 15/16] Removed reference extractor --- CHANGELOG | 3 ++- app/controllers/projects/issues_controller.rb | 4 ---- .../projects/merge_requests_controller.rb | 4 ---- spec/features/issues/inline_edit_spec.rb | 20 +++++++++---------- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 913df296590e..af013756d43e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -21,6 +21,7 @@ v 8.10.0 (unreleased) - Upgrade to Rails 4.2.7. !5236 - Add Sidekiq queue duration to transaction metrics. - Add a new column `artifacts_size` to table `ci_builds` !4964 + - Inline editing of issue & merge request title and description - Let Workhorse serve format-patch diffs - Added day name to contribution calendar tooltips - Make images fit to the size of the viewport !4810 @@ -80,6 +81,7 @@ v 8.10.0 (unreleased) - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests - Add date when user joined the team on the member page - Fix 404 redirect after validation fails importing a GitLab project + - Fix 404 redirect after validation fails importing a GitLab project - Added setting to set new users by default as external !4545 (Dravere) - Add min value for project limit field on user's form !3622 (jastkand) - Reset project pushes_since_gc when we enqueue the git gc call @@ -328,7 +330,6 @@ v 8.9.0 - Remove deprecated issues_tracker and issues_tracker_id from project model - Allow users to create confidential issues in private projects - Measure CPU time for instrumented methods - - Inline editing of issue & merge request title and description - Instrument private methods and private instance methods by default instead just public methods - Only show notes through JSON on confidential issues that the user has access to - Updated the allocations Gem to version 1.0.5 diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 2a8d2dcaa056..4d16e674508e 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -119,10 +119,6 @@ def update if params[:inline].nil? render json: @issue.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) else - ext = Gitlab::ReferenceExtractor.new(@project, current_user) - ext.analyze(@issue.title) - ext.analyze(@issue.description) - render json: { title: view_context.markdown(@issue.title, pipeline: :single_line), description: view_context.markdown(@issue.description), diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 2a50be546d69..2e6000ebaa26 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -193,10 +193,6 @@ def update if params[:inline].nil? render json: @merge_request.to_json(include: { milestone: {}, assignee: { methods: :avatar_url }, labels: { methods: :text_color } }) else - ext = Gitlab::ReferenceExtractor.new(@project, current_user) - ext.analyze(@merge_request.title) - ext.analyze(@merge_request.description) - render json: { title: view_context.markdown(@merge_request.title, pipeline: :single_line), description: view_context.markdown(@merge_request.description), diff --git a/spec/features/issues/inline_edit_spec.rb b/spec/features/issues/inline_edit_spec.rb index 7a24c04ca5ef..75f4680bf6b8 100644 --- a/spec/features/issues/inline_edit_spec.rb +++ b/spec/features/issues/inline_edit_spec.rb @@ -12,9 +12,9 @@ visit namespace_project_issue_path(project.namespace, project, issue) end - it 'should allow user to update title' do + it 'allows user to update title' do find('.js-issuable-title').click - expect(page).to have_selector('.js-issuable-edit-title', visible: true) + expect(page).to have_selector('.js-issuable-edit-title') fill_in 'issue_title', with: 'test' click_button 'Save' @@ -23,16 +23,16 @@ end end - it 'should hide title field' do + it 'hides title field' do find('.js-issuable-title').click - expect(page).to have_selector('.js-issuable-edit-title', visible: true) + expect(page).to have_selector('.js-issuable-edit-title') click_button 'Cancel' expect(page).to have_selector('.js-issuable-edit-title', visible: false) end - it 'should allow user to update description' do + it 'allows user to update description' do find('.js-issuable-description').click - expect(page).to have_selector('.js-issuable-description-field', visible: true) + expect(page).to have_selector('.js-issuable-description-field') fill_in 'issue_description', with: 'test' click_button 'Save' @@ -41,9 +41,9 @@ end end - it 'should hide description field' do + it 'hides description field' do find('.js-issuable-description').click - expect(page).to have_selector('.js-issuable-description-field', visible: true) + expect(page).to have_selector('.js-issuable-description-field') click_button 'Cancel' expect(page).to have_selector('.js-issuable-description-field', visible: false) end @@ -55,11 +55,11 @@ visit namespace_project_issue_path(project.namespace, project, issue) end - it 'should not allow editing of title' do + it 'does not allow editing of title' do expect(page).not_to have_selector('.js-issuable-title', visible: false) end - it 'should not allow editing of description' do + it 'does not allow editing of description' do expect(page).not_to have_selector('.js-issuable-description', visible: false) end end -- GitLab From a338765bc2bd704cc056ed245a1b118347e66012 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Jul 2016 09:52:20 +0100 Subject: [PATCH 16/16] Updated inline edit form --- .../javascripts/issuable_edit.js.coffee | 88 ++++--------------- app/assets/stylesheets/pages/detail_page.scss | 4 - app/assets/stylesheets/pages/issuable.scss | 54 ++++-------- app/views/projects/issues/show.html.haml | 33 ++++--- .../merge_requests/show/_mr_box.html.haml | 28 +++--- .../shared/issuable/_inline_edit.html.haml | 50 ++++------- spec/features/issues/inline_edit_spec.rb | 45 ++-------- 7 files changed, 98 insertions(+), 204 deletions(-) diff --git a/app/assets/javascripts/issuable_edit.js.coffee b/app/assets/javascripts/issuable_edit.js.coffee index 746c7cdca98b..3792d202b06e 100644 --- a/app/assets/javascripts/issuable_edit.js.coffee +++ b/app/assets/javascripts/issuable_edit.js.coffee @@ -4,89 +4,39 @@ class @IssuableEdit @removeEventListeners() @initEventListeners() - new GLForm(@elements.form) + new GLForm(@$form) getElements: -> - @elements = - form: $('.js-issuable-inline-form') - title: - element: $('.js-issuable-title') - field: $('.js-issuable-title-field') - fieldset: $('.js-issuable-edit-title') - loading: $('.js-issuable-title-loading') - description: - element: $('.js-issuable-description') - field: $('.js-task-list-field') - fieldset: $('.js-issuable-description-field') - loading: $('.js-issuable-title-loading') + @$form = $('.js-issuable-inline-form') + @$details = $('.js-issuable-details') + @$title = $('.js-issuable-title') + @$description = $('.js-issuable-description') + @$taskList = $('.detail-page-description .js-task-list-container') removeEventListeners: -> - $(document).off 'ajax:success', '.js-issuable-inline-form' - $(document).off 'click', '.js-issuable-edit-cancel' + $(document).off 'ajax:success', '.js-issuable-inline-form', @afterSave - $(document).off 'click', '.js-issuable-title' - $(document).off 'click', '.js-issuable-title-save' - - $(document).off 'click', '.js-issuable-description' - $(document).off 'click', '.js-issuable-description-save' + $(document).off 'click', '.js-inline-edit', @toggleForm + $(document).off 'click', '.js-issuable-edit-cancel', @toggleForm initEventListeners: -> $(document).on 'ajax:success', '.js-issuable-inline-form', @afterSave - $(document).on 'click', '.js-issuable-edit-cancel', @hideFields - - # Title field - $(document).on 'click', '.js-issuable-title', @showTitleEdit - $(document).on 'click', '.js-issuable-title-save', @saveTitle - - # Description field - $(document).on 'click', '.js-issuable-description', @showDescriptionEdit - $(document).on 'click', '.js-issuable-description-save', @saveDescription - - hideFields: (e) => - @hideTitleEdit(e) - @hideDescriptionEdit(e) - - showTitleEdit: => - @hideDescriptionEdit() - @elements.title.element.addClass 'hidden' - @elements.title.fieldset.removeClass 'hidden' - @elements.title.field.focus() - hideTitleEdit: (e) -> - @elements.title.fieldset.addClass 'hidden' - @elements.title.element.removeClass 'hidden' + $(document).on 'click', '.js-inline-edit', @toggleForm + $(document).on 'click', '.js-issuable-edit-cancel', @toggleForm - saveTitle: (e) => - @hideTitleEdit() - @elements.title.loading.removeClass 'hidden' - - saveDescription: (e) => - @hideDescriptionEdit(e) - @elements.description.element.addClass 'is-loading' - - showDescriptionEdit: (e) => - if $(e.target).is(':not(input,a)') - @hideTitleEdit(e) - @elements.description.element.addClass 'hidden' - @elements.description.fieldset.removeClass 'hidden' - @elements.description.field.focus() - - hideDescriptionEdit: -> - @elements.description.fieldset.addClass 'hidden' - @elements.description.element.removeClass 'hidden' + toggleForm: => + @$details.toggleClass('hidden') + @$form.toggleClass('hidden') afterSave: (e, data) => - $('.js-issuable-inline-form [type="submit"]').enable() - - @hideTitleEdit() - @hideDescriptionEdit(e) + $('[type="submit"]', @$form).enable() - @elements.title.loading.addClass 'hidden' - @elements.description.element.removeClass 'is-loading' + @toggleForm() # Update the HTML # We need HTML returned so that the markdown can be correctly created on server side - @elements.title.element.html data.title - @elements.description.element.html data.description + @$title.html data.title + @$description.html data.description - $('.detail-page-description .js-task-list-container').taskList('enable') + @$taskList.taskList('enable') diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index c3b3892f8427..1b389d83525d 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -33,10 +33,6 @@ margin-bottom: 0; } } - - .is-loading { - opacity: .5; - } } .wiki { diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 9c656da7926c..70be63b92025 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -268,7 +268,7 @@ .issuable-header-btn { background: $gray-normal; border: 1px solid $border-gray-normal; - + &:hover { background: $gray-dark; border: 1px solid $border-gray-dark; @@ -395,47 +395,27 @@ line-height: 18px; } -.issuable-title-edit { - position: relative; - padding-right: 127px; -} - -.issuable-title-edit-buttons { - position: absolute; - right: 0; - top: 0; -} - -.issuable-title-edit { - .form-control { - font-size: inherit; +.issuable-inline-label { + @media (min-width: $screen-md-min) { + text-align: right; } } -.inline-edit-box { - position: relative; +.issuable-inline-edit { + margin-top: 5px; - &:hover { - &::after { - content: ''; - position: absolute; - right: 0; - bottom: -2px; - left: 0; - border-top: 2px dashed $focus-border-color; - } + .btn { + padding-top: 3px; + padding-bottom: 3px; + color: $gray-darkest; + border-right: 1px solid $gray-darkest; + border-radius: 0; } -} -.inline-edit-description-box { - &:hover { - &::before { - content: ''; - position: absolute; - right: 0; - top: -2px; - left: 0; - border-top: 2px dashed $focus-border-color; - } + .edited-text { + display: inline-block; + margin-left: 5px; + line-height: 27px; + vertical-align: bottom; } } diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 829bda011990..faead152b0f7 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -48,22 +48,27 @@ .issue-details.issuable-details + .detail-page-description.content-block.js-issuable-details + %h2.title.js-issuable-title + = markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author + .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } + .wiki.js-issuable-description + = preserve do + = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) + %textarea.hidden.js-task-list-field + = @issue.description + %div{ class: ('issuable-inline-edit' if can?(current_user, :update_issue, @issue)) } + - if can?(current_user, :update_issue, @issue) + %button.btn.btn-transparent.has-tooltip.js-inline-edit{ type: "button", title: "Edit title and description", data: { placement: "bottom", container: "body" } } + = icon("pencil") + %span.sr-only + Edit title and description + = edited_time_ago_with_tooltip(@issue, placement: 'bottom') + #merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } } + #related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, @issue) } } + - if can?(current_user, :update_issue, @issue) = render 'shared/issuable/inline_edit', issuable: @issue - - else - .detail-page-description.content-block - %h2.title - = markdown escape_once(@issue.title), pipeline: :single_line, author: @issue.author - - if @issue.description.present? - .description{ class: can?(current_user, :update_issue, @issue) ? 'js-task-list-container' : '' } - .wiki - = preserve do - = markdown(@issue.description, cache_key: [@issue, "description"], author: @issue.author) - %textarea.hidden.js-task-list-field - = @issue.description - = edited_time_ago_with_tooltip(@issue, placement: 'bottom', html_class: 'issue_edited_ago') - #merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, @issue) } } - #related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, @issue) } } .content-block.content-block-small = render 'new_branch' diff --git a/app/views/projects/merge_requests/show/_mr_box.html.haml b/app/views/projects/merge_requests/show/_mr_box.html.haml index 32dc6e59bc62..0a33cde65fcc 100644 --- a/app/views/projects/merge_requests/show/_mr_box.html.haml +++ b/app/views/projects/merge_requests/show/_mr_box.html.haml @@ -1,14 +1,18 @@ +.detail-page-description.content-block.js-issuable-details + %h2.title.js-issuable-title + = markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author + .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} + .wiki.js-issuable-description + = preserve do + = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author) + %textarea.hidden.js-task-list-field + = @merge_request.description + %div{ class: ('issuable-inline-edit' if can?(current_user, :update_merge_request, @merge_request)) } + - if can?(current_user, :update_merge_request, @merge_request) + %button.btn.btn-transparent.has-tooltip.js-inline-edit{ type: "button", title: "Edit title and description", data: { placement: "bottom", container: "body" } } + = icon("pencil") + %span.sr-only + Edit title and description + = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') - if can?(current_user, :update_merge_request, @merge_request) = render 'shared/issuable/inline_edit', issuable: @merge_request -- else - .detail-page-description.content-block - %h2.title - = markdown escape_once(@merge_request.title), pipeline: :single_line, author: @merge_request.author - - if @merge_request.description.present? - .description{class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : ''} - .wiki - = preserve do - = markdown(@merge_request.description, cache_key: [@merge_request, "description"], author: @merge_request.author) - %textarea.hidden.js-task-list-field - = @merge_request.description - = edited_time_ago_with_tooltip(@merge_request, placement: 'bottom') diff --git a/app/views/shared/issuable/_inline_edit.html.haml b/app/views/shared/issuable/_inline_edit.html.haml index 5c3bf11be318..736224a6a8d9 100644 --- a/app/views/shared/issuable/_inline_edit.html.haml +++ b/app/views/shared/issuable/_inline_edit.html.haml @@ -1,33 +1,21 @@ -= form_for issuable, remote: true, html: { class: 'detail-page-description content-block common-note-form js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| += form_for issuable, remote: true, html: { class: 'detail-page-description content-block common-note-form hidden js-quick-submit js-issuable-inline-form', data: { type: "json" } } do |f| = hidden_field_tag :inline, true - %h2.title - %span.inline-edit-box.js-issuable-title= markdown escape_once(issuable.title), pipeline: :single_line, author: issuable.author - = icon('spinner spin', class: 'js-issuable-title-loading hidden') - .issuable-title-edit.js-issuable-edit-title.hidden - = f.text_field :title, class: 'form-control js-issuable-title-field' - .issuable-title-edit-buttons - %button.btn.btn-success.js-issuable-title-save{ type: "submit" } - Save - %button.btn.btn-default.js-issuable-edit-cancel{ type: "button" } + .row.form-group + .col-md-2.issuable-inline-label + = f.label :title, "Title", class: "label-light" + .col-md-10 + = f.text_field :title, maxlength: 255, autofocus: true, autocomplete: "off", class: "form-control", required: true + .row + .col-md-2.issuable-inline-label + = f.label :description, "Description", class: "label-light" + .col-md-10 + = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do + = render 'projects/zen', f: f, attr: :description, + classes: 'note-textarea js-task-list-field', + placeholder: "Write a comment or drag your files here..." + = render 'projects/notes/hints' + .prepend-top-10.append-bottom-10 + %button.btn.btn-success.js-issuable-description-save{ type: "submit" } + Save changes + %button.btn.btn-default.pull-right.js-issuable-edit-cancel{ type: "button" } Cancel - - if issuable.description.present? - .description{ class: 'js-task-list-container' } - .wiki.inline-edit-box.inline-edit-description-box.js-issuable-description - = preserve do - = markdown(issuable.description, cache_key: [issuable, "description"], author: issuable.author) - .js-issuable-description-field.hidden - = render layout: 'projects/md_preview', locals: { preview_class: "md-preview", referenced_users: true } do - = render 'projects/zen', f: f, attr: :description, - classes: 'note-textarea js-task-list-field', - placeholder: "Write a comment or drag your files here..." - = render 'projects/notes/hints' - .prepend-top-10.append-bottom-10 - %button.btn.btn-success.js-issuable-description-save{ type: "submit" } - Save - %button.btn.btn-default.pull-right.js-issuable-edit-cancel{ type: "button" } - Cancel - = edited_time_ago_with_tooltip(issuable, placement: 'bottom', html_class: 'issue_edited_ago') - - - if issuable.is_a? Issue - #merge-requests{ data: { url: referenced_merge_requests_namespace_project_issue_url(@project.namespace, @project, issuable) } } - #related-branches{ data: { url: related_branches_namespace_project_issue_url(@project.namespace, @project, issuable) } } diff --git a/spec/features/issues/inline_edit_spec.rb b/spec/features/issues/inline_edit_spec.rb index 75f4680bf6b8..a206f5fa6463 100644 --- a/spec/features/issues/inline_edit_spec.rb +++ b/spec/features/issues/inline_edit_spec.rb @@ -12,40 +12,15 @@ visit namespace_project_issue_path(project.namespace, project, issue) end - it 'allows user to update title' do - find('.js-issuable-title').click - expect(page).to have_selector('.js-issuable-edit-title') - fill_in 'issue_title', with: 'test' - click_button 'Save' + it 'allows user to update title and description' do + find('.js-inline-edit').click - page.within '.issuable-details' do - expect(page).to have_content 'test' - end - end - - it 'hides title field' do - find('.js-issuable-title').click - expect(page).to have_selector('.js-issuable-edit-title') - click_button 'Cancel' - expect(page).to have_selector('.js-issuable-edit-title', visible: false) - end - - it 'allows user to update description' do - find('.js-issuable-description').click - expect(page).to have_selector('.js-issuable-description-field') - fill_in 'issue_description', with: 'test' - click_button 'Save' + fill_in 'issue_title', with: 'title test' + fill_in 'issue_description', with: 'description test' - page.within '.issuable-details' do - expect(page).to have_content 'test' - end - end - - it 'hides description field' do - find('.js-issuable-description').click - expect(page).to have_selector('.js-issuable-description-field') - click_button 'Cancel' - expect(page).to have_selector('.js-issuable-description-field', visible: false) + click_button 'Save changes' + expect(page).to have_content 'title test' + expect(page).to have_content 'description test' end end @@ -56,11 +31,7 @@ end it 'does not allow editing of title' do - expect(page).not_to have_selector('.js-issuable-title', visible: false) - end - - it 'does not allow editing of description' do - expect(page).not_to have_selector('.js-issuable-description', visible: false) + expect(page).not_to have_selector('.js-inline-edit', visible: false) end end end -- GitLab