summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2015-06-05 13:37:08 +0000
committerDmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>2015-06-05 13:37:08 +0000
commit5a026152b745d5a716c522bc58a76682ee534e25 (patch)
tree0579a0d6522650f0ae929b6d200d2ddcc746db6c
parent6f7bf4e4f0ea40c4f69354b8ce75c77af4fab5cb (diff)
parent5256b5cc060338fb597e3519a18bf6a3faa4cf8c (diff)
downloadgitlab-ce-5a026152b745d5a716c522bc58a76682ee534e25.tar.gz
Merge branch 'warn-about-referenced-users' into 'master'
Show warning when a comment will add 10 or more people to the discussion. Addresses internal issue https://dev.gitlab.org/gitlab/gitlabhq/issues/2054 New issue: ![Screen_Shot_2015-06-02_at_14.48.46](https://gitlab.com/gitlab-org/gitlab-ce/uploads/6771ff8748b9b548a9f0f32a5a8b9bb1/Screen_Shot_2015-06-02_at_14.48.46.png) New comment: ![Screen_Shot_2015-06-02_at_14.48.51](https://gitlab.com/gitlab-org/gitlab-ce/uploads/25ec5f06490e1e6b36e453e055a7b403/Screen_Shot_2015-06-02_at_14.48.51.png) See merge request !754
-rw-r--r--CHANGELOG1
-rw-r--r--app/assets/javascripts/dropzone_input.js.coffee52
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js.coffee20
-rw-r--r--app/assets/stylesheets/generic/markdown_area.scss16
-rw-r--r--app/assets/stylesheets/generic/mobile.scss4
-rw-r--r--app/assets/stylesheets/generic/zen.scss5
-rw-r--r--app/assets/stylesheets/pages/note_form.scss6
-rw-r--r--app/controllers/projects_controller.rb12
-rw-r--r--app/services/projects/participants_service.rb4
-rw-r--r--app/views/layouts/_head.html.haml4
-rw-r--r--app/views/layouts/_page.html.haml2
-rw-r--r--app/views/layouts/application.html.haml2
-rw-r--r--app/views/layouts/project.html.haml8
-rw-r--r--app/views/projects/_issuable_form.html.haml2
-rw-r--r--app/views/projects/_md_preview.html.haml37
-rw-r--r--app/views/projects/issues/_form.html.haml2
-rw-r--r--app/views/projects/merge_requests/_form.html.haml2
-rw-r--r--app/views/projects/merge_requests/_new_submit.html.haml2
-rw-r--r--app/views/projects/milestones/_form.html.haml2
-rw-r--r--app/views/projects/notes/_form.html.haml7
-rw-r--r--app/views/projects/wikis/_form.html.haml3
21 files changed, 133 insertions, 60 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 4d7d406b43f..624dd3a5c48 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,7 @@ v 7.12.0 (unreleased)
- Fix timeout when rendering file with thousands of lines.
- Don't notify users mentioned in code blocks or blockquotes.
- Omit link to generate labels if user does not have access to create them (Stan Hu)
+ - Show warning when a comment will add 10 or more people to the discussion.
- Disable changing of the source branch in merge request update API (Stan Hu)
- Shorten merge request WIP text.
- Add option to disallow users from registering any application to use GitLab as an OAuth provider
diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee
index fca2a290e2d..a7476146010 100644
--- a/app/assets/javascripts/dropzone_input.js.coffee
+++ b/app/assets/javascripts/dropzone_input.js.coffee
@@ -10,12 +10,17 @@ class @DropzoneInput
iconSpinner = "<i class=\"fa fa-spinner fa-spin div-dropzone-icon\"></i>"
btnAlert = "<button type=\"button\"" + alertAttr + ">&times;</button>"
project_uploads_path = window.project_uploads_path or null
+ markdown_preview_path = window.markdown_preview_path or null
max_file_size = gon.max_file_size or 10
form_textarea = $(form).find("textarea.markdown-area")
form_textarea.wrap "<div class=\"div-dropzone\"></div>"
- form_textarea.bind 'paste', (event) =>
+ form_textarea.on 'paste', (event) =>
handlePaste(event)
+ form_textarea.on "input", ->
+ hideReferencedUsers()
+ form_textarea.on "blur", ->
+ renderMarkdown()
form_dropzone = $(form).find('.div-dropzone')
form_dropzone.parent().addClass "div-dropzone-wrapper"
@@ -45,16 +50,7 @@ class @DropzoneInput
form.find(".md-write-holder").hide()
form.find(".md-preview-holder").show()
- preview = form.find(".js-md-preview")
- mdText = form.find(".markdown-area").val()
- if mdText.trim().length is 0
- preview.text "Nothing to preview."
- else
- preview.text "Loading..."
- $.post($(this).data("url"),
- md_text: mdText
- ).success (previewData) ->
- preview.html previewData
+ renderMarkdown()
# Write button
$(document).off "click", ".js-md-write-button"
@@ -133,6 +129,40 @@ class @DropzoneInput
child = $(dropzone[0]).children("textarea")
+ hideReferencedUsers = ->
+ referencedUsers = form.find(".referenced-users")
+ referencedUsers.hide()
+
+ renderReferencedUsers = (users) ->
+ referencedUsers = form.find(".referenced-users")
+
+ if referencedUsers.length
+ if users.length >= 10
+ referencedUsers.show()
+ referencedUsers.find(".js-referenced-users-count").text users.length
+ else
+ referencedUsers.hide()
+
+ renderMarkdown = ->
+ preview = form.find(".js-md-preview")
+ mdText = form.find(".markdown-area").val()
+ if mdText.trim().length is 0
+ preview.text "Nothing to preview."
+ hideReferencedUsers()
+ else
+ preview.text "Loading..."
+ $.ajax(
+ type: "POST",
+ url: markdown_preview_path,
+ data: {
+ text: mdText
+ },
+ dataType: "json"
+ ).success (data) ->
+ preview.html data.body
+
+ renderReferencedUsers data.references.users
+
formatLink = (link) ->
text = "[#{link.alt}](#{link.url})"
text = "!#{text}" if link.is_image
diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee
index 4eb3f3c03f3..7967892f856 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.coffee
+++ b/app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -10,7 +10,7 @@ GitLab.GfmAutoComplete =
# Team Members
Members:
- template: '<li>${username} <small>${name}</small></li>'
+ template: '<li>${username} <small>${title}</small></li>'
# Issues and MergeRequests
Issues:
@@ -34,7 +34,13 @@ GitLab.GfmAutoComplete =
searchKey: 'search'
callbacks:
beforeSave: (members) ->
- $.map members, (m) -> name: m.name, username: m.username, search: "#{m.username} #{m.name}"
+ $.map members, (m) ->
+ title = m.name
+ title += " (#{m.count})" if m.count
+
+ username: m.username
+ title: sanitize(title)
+ search: sanitize("#{m.username} #{m.name}")
input.atwho
at: '#'
@@ -44,7 +50,10 @@ GitLab.GfmAutoComplete =
insertTpl: '${atwho-at}${id}'
callbacks:
beforeSave: (issues) ->
- $.map issues, (i) -> id: i.iid, title: sanitize(i.title), search: "#{i.iid} #{i.title}"
+ $.map issues, (i) ->
+ id: i.iid
+ title: sanitize(i.title)
+ search: "#{i.iid} #{i.title}"
input.atwho
at: '!'
@@ -54,7 +63,10 @@ GitLab.GfmAutoComplete =
insertTpl: '${atwho-at}${id}'
callbacks:
beforeSave: (merges) ->
- $.map merges, (m) -> id: m.iid, title: sanitize(m.title), search: "#{m.iid} #{m.title}"
+ $.map merges, (m) ->
+ id: m.iid
+ title: sanitize(m.title)
+ search: "#{m.iid} #{m.title}"
input.one 'focus', =>
$.getJSON(@dataSource).done (data) ->
diff --git a/app/assets/stylesheets/generic/markdown_area.scss b/app/assets/stylesheets/generic/markdown_area.scss
index eb39b6bb7e9..f94677d1925 100644
--- a/app/assets/stylesheets/generic/markdown_area.scss
+++ b/app/assets/stylesheets/generic/markdown_area.scss
@@ -52,6 +52,22 @@
transition: opacity 200ms ease-in-out;
}
+.md-area {
+ position: relative;
+}
+
+.md-header ul {
+ float: left;
+}
+
+.referenced-users {
+ padding: 10px 0;
+ color: #999;
+ margin-left: 10px;
+ margin-top: 1px;
+ margin-right: 130px;
+}
+
.md-preview-holder {
background: #FFF;
border: 1px solid #ddd;
diff --git a/app/assets/stylesheets/generic/mobile.scss b/app/assets/stylesheets/generic/mobile.scss
index 74108c1f086..e61b39f1ac3 100644
--- a/app/assets/stylesheets/generic/mobile.scss
+++ b/app/assets/stylesheets/generic/mobile.scss
@@ -19,6 +19,10 @@
}
}
+ .referenced-users {
+ margin-right: 0;
+ }
+
.issues-filters,
.dash-projects-filters,
.check-all-holder {
diff --git a/app/assets/stylesheets/generic/zen.scss b/app/assets/stylesheets/generic/zen.scss
index bcb8bbe3134..7ab01187a02 100644
--- a/app/assets/stylesheets/generic/zen.scss
+++ b/app/assets/stylesheets/generic/zen.scss
@@ -1,6 +1,4 @@
.zennable {
- position: relative;
-
.zen-toggle-comment {
display: none;
}
@@ -8,8 +6,9 @@
.zen-enter-link {
color: #888;
position: absolute;
- top: -26px;
+ top: 0px;
right: 4px;
+ line-height: 40px;
}
.zen-leave-link {
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index a0522030785..203f9374cee 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -39,11 +39,8 @@
.new_note, .edit_note {
.buttons {
- float: left;
margin-top: 8px;
- }
- .clearfix {
- margin-bottom: 0;
+ margin-bottom: 3px;
}
.note-preview-holder {
@@ -82,7 +79,6 @@
.note-form-actions {
background: #F9F9F9;
- height: 45px;
.note-form-option {
margin-top: 8px;
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 4ca5fc65459..be5968cd7b0 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -151,7 +151,17 @@ class ProjectsController < ApplicationController
end
def markdown_preview
- render text: view_context.markdown(params[:md_text])
+ text = params[:text]
+
+ ext = Gitlab::ReferenceExtractor.new(@project, current_user)
+ ext.analyze(text)
+
+ render json: {
+ body: view_context.markdown(text),
+ references: {
+ users: ext.users.map(&:username)
+ }
+ }
end
private
diff --git a/app/services/projects/participants_service.rb b/app/services/projects/participants_service.rb
index b91590a1a90..0004a399f47 100644
--- a/app/services/projects/participants_service.rb
+++ b/app/services/projects/participants_service.rb
@@ -38,13 +38,13 @@ module Projects
def groups
current_user.authorized_groups.sort_by(&:path).map do |group|
count = group.users.count
- { username: group.path, name: "#{group.name} (#{count})" }
+ { username: group.path, name: group.name, count: count }
end
end
def all_members
count = project.team.members.flatten.count
- [{ username: "all", name: "All Project and Group Members (#{count})" }]
+ [{ username: "all", name: "All Project and Group Members", count: count }]
end
end
end
diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml
index b1a57d9824e..4d8c5656a25 100644
--- a/app/views/layouts/_head.html.haml
+++ b/app/views/layouts/_head.html.haml
@@ -15,8 +15,10 @@
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1'}
%meta{name: 'theme-color', content: '#474D57'}
- = yield(:meta_tags)
+ = yield :meta_tags
= render 'layouts/google_analytics' if extra_config.has_key?('google_analytics_id')
= render 'layouts/piwik' if extra_config.has_key?('piwik_url') && extra_config.has_key?('piwik_site_id')
= render 'layouts/bootlint' if Rails.env.development?
+
+ = yield :scripts_head
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index c1283734d25..54fcbca6bc6 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -22,5 +22,3 @@
= render "layouts/flash"
.clearfix
= yield
-
-= yield :embedded_scripts
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index 155825cc4c2..ff23913d7d6 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -8,3 +8,5 @@
= render "layouts/header/public", title: header_title
= render 'layouts/page', sidebar: sidebar
+
+ = yield :scripts_body
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 4aeb9d397d2..03c7ba8c73f 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -2,7 +2,13 @@
- header_title project_title(@project)
- sidebar "project" unless sidebar
-- content_for :embedded_scripts do
+- content_for :scripts_head do
+ -if current_user
+ :javascript
+ window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
+ window.markdown_preview_path = "#{markdown_preview_namespace_project_path(@project.namespace, @project)}";
+
+- content_for :scripts_body do
= render "layouts/init_auto_complete" if current_user
= render template: "layouts/application"
diff --git a/app/views/projects/_issuable_form.html.haml b/app/views/projects/_issuable_form.html.haml
index 2c5b24b8130..491e2107da4 100644
--- a/app/views/projects/_issuable_form.html.haml
+++ b/app/views/projects/_issuable_form.html.haml
@@ -24,7 +24,7 @@
= f.label :description, 'Description', class: 'control-label'
.col-sm-10
- = render layout: 'projects/md_preview', locals: { preview_class: "wiki" } do
+ = render layout: 'projects/md_preview', locals: { preview_class: "wiki", referenced_users: true } do
= render 'projects/zen', f: f, attr: :description,
classes: 'description form-control'
.col-sm-12.hint
diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml
index b869fd6e12a..a831481cf80 100644
--- a/app/views/projects/_md_preview.html.haml
+++ b/app/views/projects/_md_preview.html.haml
@@ -1,13 +1,24 @@
-%ul.nav.nav-tabs
- %li.active
- = link_to '#md-write-holder', class: 'js-md-write-button' do
- Write
- %li
- = link_to '#md-preview-holder', class: 'js-md-preview-button',
- data: { url: markdown_preview_namespace_project_path(@project.namespace, @project) } do
- Preview
-%div
- .md-write-holder
- = yield
- .md.md-preview-holder.hide
- .js-md-preview{class: (preview_class if defined?(preview_class))}
+.md-area
+ .md-header.clearfix
+ %ul.nav.nav-tabs
+ %li.active
+ = link_to '#md-write-holder', class: 'js-md-write-button' do
+ Write
+ %li
+ = link_to '#md-preview-holder', class: 'js-md-preview-button' do
+ Preview
+
+ - if defined?(referenced_users) && referenced_users
+ %span.referenced-users.pull-left.hide
+ = icon('exclamation-triangle')
+ You are about to add
+ %strong
+ %span.js-referenced-users-count 0
+ people
+ to the discussion. Proceed with caution.
+
+ %div
+ .md-write-holder
+ = yield
+ .md.md-preview-holder.hide
+ .js-md-preview{class: (preview_class if defined?(preview_class))}
diff --git a/app/views/projects/issues/_form.html.haml b/app/views/projects/issues/_form.html.haml
index 7d7217eb2a8..8d2564be55e 100644
--- a/app/views/projects/issues/_form.html.haml
+++ b/app/views/projects/issues/_form.html.haml
@@ -10,5 +10,3 @@
$('#issue_assignee_id').val("#{current_user.id}").trigger("change");
e.preventDefault();
});
-
- window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index 1c7160bce5f..be73f087449 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -8,5 +8,3 @@
$('#merge_request_assignee_id').val("#{current_user.id}").trigger("change");
e.preventDefault();
});
-
- window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/merge_requests/_new_submit.html.haml b/app/views/projects/merge_requests/_new_submit.html.haml
index 9a2edbf0a8c..6792104569b 100644
--- a/app/views/projects/merge_requests/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/_new_submit.html.haml
@@ -51,8 +51,6 @@
e.preventDefault();
});
- window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
-
:javascript
var merge_request
merge_request = new MergeRequest({
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 95b7070ce5c..5650607f31f 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -50,5 +50,3 @@
dateFormat: "yy-mm-dd",
onSelect: function(dateText, inst) { $("#milestone_due_date").val(dateText) }
}).datepicker("setDate", $.datepicker.parseDate('yy-mm-dd', $('#milestone_due_date').val()));
-
- window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/notes/_form.html.haml b/app/views/projects/notes/_form.html.haml
index 2ada6cb6700..f28b3e9b508 100644
--- a/app/views/projects/notes/_form.html.haml
+++ b/app/views/projects/notes/_form.html.haml
@@ -5,7 +5,7 @@
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
- = render layout: 'projects/md_preview', locals: { preview_class: "note-text" } do
+ = render layout: 'projects/md_preview', locals: { preview_class: "note-text", referenced_users: true } do
= render 'projects/zen', f: f, attr: :note,
classes: 'note_text js-note-text'
@@ -15,10 +15,7 @@
.error-alert
.note-form-actions
- .buttons
+ .buttons.clearfix
= f.submit 'Add Comment', class: "btn comment-btn btn-grouped js-comment-button"
= yield(:note_actions)
%a.btn.grouped.js-close-discussion-note-form Cancel
-
-:javascript
- window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";
diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml
index 9fbfa0b1aeb..2a8ceaa2844 100644
--- a/app/views/projects/wikis/_form.html.haml
+++ b/app/views/projects/wikis/_form.html.haml
@@ -41,6 +41,3 @@
- else
= f.submit 'Create page', class: "btn-create btn"
= link_to "Cancel", namespace_project_wiki_path(@project.namespace, @project, :home), class: "btn btn-cancel"
-
-:javascript
- window.project_uploads_path = "#{namespace_project_uploads_path @project.namespace, @project}";