Commit f058b52b authored by Douwe Maan's avatar Douwe Maan
Browse files

Merge branch 'master' into new-resolvable-discussion

......@@ -356,3 +356,5 @@ gem 'sys-filesystem', '~> 1.1.6'
# Gitaly GRPC client
gem 'gitaly', '~> 0.5.0'
gem 'toml-rb', '~> 0.3.15', require: false
......@@ -117,6 +117,7 @@ GEM
chronic_duration (0.10.6)
numerizer (~> 0.1.1)
chunky_png (1.3.5)
citrus (3.0.2)
cliver (0.3.2)
coderay (1.1.1)
coercible (1.0.0)
......@@ -784,6 +785,8 @@ GEM
tilt (2.0.6)
timecop (0.8.1)
timfel-krb5-auth (0.8.3)
toml-rb (0.3.15)
citrus (~> 3.0, > 3.0)
tool (0.2.3)
truncato (0.7.8)
htmlentities (~> 4.3.1)
......@@ -1015,6 +1018,7 @@ DEPENDENCIES
test_after_commit (~> 1.1)
thin (~> 1.7.0)
timecop (~> 0.8.0)
toml-rb (~> 0.3.15)
truncato (~> 0.7.8)
u2f (~> 0.2.1)
uglifier (~> 2.7.2)
......
......@@ -73,11 +73,20 @@ These types of merge requests need special consideration:
and a dedicated team with front-end, back-end, and UX.
* **Small features**: any other feature request.
**Large features** must be with a maintainer **by the 1st**. It's OK if they
aren't completely done, but this allows the maintainer enough time to make the
decision about whether this can make it in before the freeze. If the maintainer
doesn't think it will make it, they should inform the developers working on it
and the Product Manager responsible for the feature.
**Large features** must be with a maintainer **by the 1st**. This means that:
* There is a merge request (even if it's WIP).
* The person (or people, if it needs a frontend and backend maintainer) who will
ultimately be responsible for merging this have been pinged on the MR.
It's OK if merge request isn't completely done, but this allows the maintainer
enough time to make the decision about whether this can make it in before the
freeze. If the maintainer doesn't think it will make it, they should inform the
developers working on it and the Product Manager responsible for the feature.
The maintainer can also choose to assign a reviewer to perform an initial
review, but this way the maintainer is unlikely to be surprised by receiving an
MR later in the cycle.
**Small features** must be with a reviewer (not necessarily maintainer) **by the
3rd**.
......
......@@ -31,7 +31,7 @@
svg {
width: 20px;
height: auto;
height: 20px;
fill: $gl-text-color-secondary;
}
......
......@@ -19,7 +19,7 @@ ul.notes {
svg {
width: 18px;
height: auto;
height: 18px;
fill: $gray-darkest;
position: absolute;
left: 30px;
......
......@@ -7,7 +7,7 @@ module SystemNoteHelper
'closed' => 'icon_status_closed',
'time_tracking' => 'icon_stopwatch',
'assignee' => 'icon_user',
'title' => 'icon_pencil',
'title' => 'icon_edit',
'task' => 'icon_check_square_o',
'label' => 'icon_tags',
'cross_reference' => 'icon_random',
......
......@@ -10,6 +10,7 @@
= custom_icon("icon_code_fork")
.event-title
%span.author_name= link_to_author event
%span{ class: event.action_name }
- if event.target
= event.action_name
......
......@@ -2,6 +2,7 @@
= custom_icon("icon_status_open")
.event-title
%span.author_name= link_to_author event
%span{ class: event.action_name }
= event_action_name(event)
......
......@@ -2,6 +2,7 @@
= custom_icon("icon_comment_o")
.event-title
%span.author_name= link_to_author event
= event.action_name
= event_note_title_html(event)
......
......@@ -7,6 +7,7 @@
= custom_icon("icon_commit")
.event-title
%span.author_name= link_to_author event
%span.pushed #{event.action_name} #{event.ref_type}
%strong
- commits_link = namespace_project_commits_path(project.namespace, project, event.ref_name)
......
......@@ -7,7 +7,7 @@
#blob-content-holder.tree-holder
.file-holder
= render "projects/blob/header", blob: @blob
= render "projects/blob/header", blob: @blob, blame: true
.table-responsive.file-content.blame.code.js-syntax-highlight
%table
......
- blame = local_assigns.fetch(:blame, false)
.js-file-title.file-title-flex-parent
.file-header-content
= blob_icon blob.mode, blob.name
......@@ -12,14 +13,14 @@
.file-actions.hidden-xs
.btn-group{ role: "group" }<
= copy_blob_content_button(blob) if blob_text_viewable?(blob)
= copy_blob_content_button(blob) if !blame && blob_text_viewable?(blob)
= open_raw_file_button(namespace_project_raw_path(@project.namespace, @project, @id))
= view_on_environment_button(@commit.sha, @path, @environment) if @environment
.btn-group{ role: "group" }<
-# only show normal/blame view links for text files
- if blob_text_viewable?(blob)
- if current_page? namespace_project_blame_path(@project.namespace, @project, @id)
- if blame
= link_to 'Normal view', namespace_project_blob_path(@project.namespace, @project, @id),
class: 'btn btn-sm'
- else
......
---
title: Upgrade webpack to v2.3.3 and webpack-dev-server to v2.4.2
merge_request: 10552
author:
---
title: Add indication for closed or merged issuables in GFM
merge_request: 9462
author: Adam Buckland
class Spinach::Features::ProjectMergeRequestsAcceptance < Spinach::FeatureSteps
include LoginHelpers
include GitlabRoutingHelper
include WaitForAjax
step 'I am on the Merge Request detail page' do
visit merge_request_path(@merge_request)
......@@ -20,10 +21,18 @@ class Spinach::Features::ProjectMergeRequestsAcceptance < Spinach::FeatureSteps
step 'I should see the Remove Source Branch button' do
expect(page).to have_link('Remove source branch')
# Wait for AJAX requests to complete so they don't blow up if they are
# only handled after `DatabaseCleaner` has already run
wait_for_ajax
end
step 'I should not see the Remove Source Branch button' do
expect(page).not_to have_link('Remove source branch')
# Wait for AJAX requests to complete so they don't blow up if they are
# only handled after `DatabaseCleaner` has already run
wait_for_ajax
end
step 'There is an open Merge Request' do
......
......@@ -97,7 +97,7 @@ module SharedProject
step 'I should see project "Shop" activity feed' do
project = Project.find_by(name: "Shop")
expect(page).to have_content "pushed new branch fix at #{project.name_with_namespace}"
expect(page).to have_content "#{@user.name} pushed new branch fix at #{project.name_with_namespace}"
end
step 'I should see project settings' do
......
module Banzai
module Filter
# HTML filter that appends state information to issuable links.
# Runs as a post-process filter as issuable state might change whilst
# Markdown is in the cache.
#
# This filter supports cross-project references.
class IssuableStateFilter < HTML::Pipeline::Filter
VISIBLE_STATES = %w(closed merged).freeze
def call
extractor = Banzai::IssuableExtractor.new(project, current_user)
issuables = extractor.extract([doc])
issuables.each do |node, issuable|
if VISIBLE_STATES.include?(issuable.state)
node.children.last.content += " [#{issuable.state}]"
end
end
doc
end
private
def current_user
context[:current_user]
end
def project
context[:project]
end
end
end
end
......@@ -7,7 +7,7 @@ module Filter
#
class RedactorFilter < HTML::Pipeline::Filter
def call
Redactor.new(project, current_user).redact([doc])
Redactor.new(project, current_user).redact([doc]) unless context[:skip_redaction]
doc
end
......
module Banzai
# Extract references to issuables from multiple documents
# This populates RequestStore cache used in Banzai::ReferenceParser::IssueParser
# and Banzai::ReferenceParser::MergeRequestParser
# Populating the cache should happen before processing documents one-by-one
# so we can avoid N+1 queries problem
class IssuableExtractor
QUERY = %q(
descendant-or-self::a[contains(concat(" ", @class, " "), " gfm ")]
[@data-reference-type="issue" or @data-reference-type="merge_request"]
).freeze
attr_reader :project, :user
def initialize(project, user)
@project = project
@user = user
end
# Returns Hash in the form { node => issuable_instance }
def extract(documents)
nodes = documents.flat_map do |document|
document.xpath(QUERY)
end
issue_parser = Banzai::ReferenceParser::IssueParser.new(project, user)
merge_request_parser = Banzai::ReferenceParser::MergeRequestParser.new(project, user)
issue_parser.issues_for_nodes(nodes).merge(
merge_request_parser.merge_requests_for_nodes(nodes)
)
end
end
end
......@@ -31,7 +31,8 @@ def initialize(project, user = nil, redaction_context = {})
#
# Returns the same input objects.
def render(objects, attribute)
documents = render_objects(objects, attribute)
documents = render_documents(objects, attribute)
documents = post_process_documents(documents, objects, attribute)
redacted = redact_documents(documents)
objects.each_with_index do |object, index|
......@@ -41,9 +42,24 @@ def render(objects, attribute)
end
end
# Renders the attribute of every given object.
def render_objects(objects, attribute)
render_attributes(objects, attribute)
private
def render_documents(objects, attribute)
pipeline = HTML::Pipeline.new([])
objects.map do |object|
pipeline.to_document(Banzai.render_field(object, attribute))
end
end
def post_process_documents(documents, objects, attribute)
# Called here to populate cache, refer to IssuableExtractor docs
IssuableExtractor.new(project, user).extract(documents)
documents.zip(objects).map do |document, object|
context = context_for(object, attribute)
Banzai::Pipeline[:post_process].to_document(document, context)
end
end
# Redacts the list of documents.
......@@ -57,25 +73,15 @@ def redact_documents(documents)
# Returns a Banzai context for the given object and attribute.
def context_for(object, attribute)
context = base_context.dup
context = context.merge(object.banzai_render_context(attribute))
context
end
# Renders the attributes of a set of objects.
#
# Returns an Array of `Nokogiri::HTML::Document`.
def render_attributes(objects, attribute)
objects.map do |object|
string = Banzai.render_field(object, attribute)
context = context_for(object, attribute)
Banzai::Pipeline[:relative_link].to_document(string, context)
end
base_context.merge(object.banzai_render_context(attribute))
end
def base_context
@base_context ||= @redaction_context.merge(current_user: user, project: project)
@base_context ||= @redaction_context.merge(
current_user: user,
project: project,
skip_redaction: true
)
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment