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
This commit is contained in:
Dmitriy Zaporozhets 2015-06-05 13:37:08 +00:00
commit 5a026152b7
21 changed files with 133 additions and 60 deletions

View file

@ -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

View file

@ -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

View file

@ -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) ->

View file

@ -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;

View file

@ -19,6 +19,10 @@
}
}
.referenced-users {
margin-right: 0;
}
.issues-filters,
.dash-projects-filters,
.check-all-holder {

View file

@ -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 {

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -22,5 +22,3 @@
= render "layouts/flash"
.clearfix
= yield
= yield :embedded_scripts

View file

@ -8,3 +8,5 @@
= render "layouts/header/public", title: header_title
= render 'layouts/page', sidebar: sidebar
= yield :scripts_body

View file

@ -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"

View file

@ -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

View file

@ -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))}

View file

@ -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}";

View file

@ -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}";

View file

@ -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({

View file

@ -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}";

View file

@ -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}";

View file

@ -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}";