Commit 0221d6c9 authored by Nick Thomas's avatar Nick Thomas

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2017-07-19

parents 7aa53529 8f2fce56
Please view this file on the master branch, on stable branches it's out of date.
## 9.3.8 (2017-07-19)
- Escape symbols in exported CSV columns to prevent command execution in Microsoft Excel.
- Prevent mirror user to be assigned to users other than the current one.
## 9.3.7 (2017-07-18)
- No changes.
......@@ -72,6 +77,11 @@ Please view this file on the master branch, on stable branches it's out of date.
- Fix: /unassign by default unassigns everyone. Implement /reassign command.
- Speed up checking for approvers remaining.
## 9.2.8 (2017-07-19)
- Escape symbols in exported CSV columns to prevent command execution in Microsoft Excel.
- Prevent mirror user to be assigned to users other than the current one.
## 9.2.7 (2017-06-21)
- Geo: fixed Dynamic Backoff strategy that was not being used by workers. !2128
......@@ -128,6 +138,11 @@ Please view this file on the master branch, on stable branches it's out of date.
- Feature availability check using feature list AND license addons.
- Disable mirror workers for Geo secondaries.
## 9.1.8 (2017-07-19)
- Escape symbols in exported CSV columns to prevent command execution in Microsoft Excel.
- Prevent mirror user to be assigned to users other than the current one.
## 9.1.7 (2017-06-07)
- No changes.
......@@ -207,6 +222,11 @@ Please view this file on the master branch, on stable branches it's out of date.
- Show user cohorts data when usage ping is enabled.
- Visualise Canary Deployments.
## 9.0.11 (2017-07-19)
- Escape symbols in exported CSV columns to prevent command execution in Microsoft Excel.
- Prevent mirror user to be assigned to users other than the current one.
## 9.0.10 (2017-06-07)
- No changes.
......@@ -299,6 +319,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- [Elasticsearch] More efficient search.
- Get Geo secondaries nodes statuses over AJAX.
## 8.17.7 (2017-07-19)
- Prevent mirror user to be assigned to users other than the current one.
## 8.17.6 (2017-05-05)
- Respect project features when searching alternative branches with elasticsearch enabled.
......
......@@ -2,6 +2,13 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 9.3.8 (2017-07-19)
- Improve support for external issue references. !12485
- Renders 404 if given project is not readable by the user on Todos dashboard.
- Use uploads/system directory for personal snippets.
- Remove uploads/appearance symlink. A leftover from a previous migration.
## 9.3.7 (2017-07-18)
- Prevent bad data being added to application settings when Redis is unavailable. !12750
......@@ -264,6 +271,13 @@ entry.
- Remove foreigh key on ci_trigger_schedules only if it exists.
- Allow translation of Pipeline Schedules.
## 9.2.8 (2017-07-19)
- Improve support for external issue references. !12485
- Renders 404 if given project is not readable by the user on Todos dashboard.
- Fix incorrect project authorizations.
- Remove uploads/appearance symlink. A leftover from a previous migration.
## 9.2.7 (2017-06-21)
- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
......@@ -510,6 +524,13 @@ entry.
- Fix preemptive scroll bar on user activity calendar.
- Pipeline chat notifications convert seconds to minutes and hours.
## 9.1.8 (2017-07-19)
- Improve support for external issue references. !12485
- Renders 404 if given project is not readable by the user on Todos dashboard.
- Fix incorrect project authorizations.
- Remove uploads/appearance symlink. A leftover from a previous migration.
## 9.1.7 (2017-06-07)
- No changes.
......@@ -823,6 +844,12 @@ entry.
- Only send chat notifications for the default branch.
- Don't fill in the default kubernetes namespace.
## 9.0.11 (2017-07-19)
- Renders 404 if given project is not readable by the user on Todos dashboard.
- Fix incorrect project authorizations.
- Remove uploads/appearance symlink. A leftover from a previous migration.
## 9.0.10 (2017-06-07)
- No changes.
......@@ -1193,6 +1220,11 @@ entry.
- Change development tanuki favicon colors to match logo color order.
- API issues - support filtering by iids.
## 8.17.7 (2017-07-19)
- Renders 404 if given project is not readable by the user on Todos dashboard.
- Fix incorrect project authorizations.
## 8.17.6 (2017-05-05)
- Enforce project features when searching blobs and wikis.
......
......@@ -172,6 +172,9 @@ gem 'rainbow', '~> 2.2'
# GitLab settings
gem 'settingslogic', '~> 2.0.9'
# Linear-time regex library for untrusted regular expressions
gem 're2', '~> 1.0.0'
# Misc
gem 'version_sorter', '~> 2.1.0'
......
......@@ -686,6 +686,7 @@ GEM
debugger-ruby_core_source (~> 1.3)
rdoc (4.2.2)
json (~> 1.4)
re2 (1.0.0)
recaptcha (3.0.0)
json
recursive-open-struct (1.0.0)
......@@ -1094,6 +1095,7 @@ DEPENDENCIES
raindrops (~> 0.18)
rblineprof (~> 0.3.6)
rdoc (~> 4.2)
re2 (~> 1.0.0)
recaptcha (~> 3.0)
redcarpet (~> 3.4)
redis (~> 3.2)
......
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */
/* global ProjectSelect */
/* global ShortcutsNavigation */
/* global IssuableIndex */
/* global ShortcutsIssuable */
......@@ -163,6 +164,9 @@ import AuditLogs from './audit_logs';
shortcut_handler = new ShortcutsIssuable();
new ZenMode();
break;
case 'dashboard:milestones:index':
new ProjectSelect();
break;
case 'projects:milestones:show':
case 'groups:milestones:show':
case 'dashboard:milestones:show':
......@@ -172,6 +176,7 @@ import AuditLogs from './audit_logs';
case 'groups:issues':
case 'groups:merge_requests':
new UsersSelect();
new ProjectSelect();
break;
case 'dashboard:todos:index':
new Todos();
......@@ -266,6 +271,7 @@ import AuditLogs from './audit_logs';
break;
case 'dashboard:issues':
case 'dashboard:merge_requests':
new ProjectSelect();
new UsersSelect();
break;
case 'projects:commit:show':
......
......@@ -5,12 +5,15 @@ export default class GroupName {
constructor() {
this.titleContainer = document.querySelector('.js-title-container');
this.title = this.titleContainer.querySelector('.title');
this.titleWidth = this.title.offsetWidth;
this.groupTitle = this.titleContainer.querySelector('.group-title');
this.groups = this.titleContainer.querySelectorAll('.group-path');
this.toggle = null;
this.isHidden = false;
this.init();
if (this.title) {
this.titleWidth = this.title.offsetWidth;
this.groupTitle = this.titleContainer.querySelector('.group-title');
this.groups = this.titleContainer.querySelectorAll('.group-path');
this.toggle = null;
this.isHidden = false;
this.init();
}
}
init() {
......
......@@ -110,6 +110,14 @@ import Api from './api';
dropdownCssClass: "ajax-project-dropdown"
});
});
$('.new-project-item-select-button').on('click', function() {
$('.project-item-select', this.parentNode).select2('open');
});
$('.project-item-select').on('click', function() {
window.location = `${$(this).val()}/${this.dataset.relativePath}`;
});
}
return ProjectSelect;
......
......@@ -330,7 +330,7 @@ header.navbar-gitlab-new {
white-space: nowrap;
> a {
&:last-of-type {
&:last-of-type:not(:first-child) {
font-weight: 600;
}
}
......@@ -384,6 +384,7 @@ header.navbar-gitlab-new {
&::after {
content: "/";
margin: 0 2px 0 5px;
color: rgba($black, .65);
}
}
......@@ -396,3 +397,13 @@ header.navbar-gitlab-new {
color: $gl-text-color;
}
}
.top-area {
.nav-controls-new-nav {
.dropdown {
@media (min-width: $screen-sm-min) {
margin-right: 0;
}
}
}
}
......@@ -178,6 +178,10 @@
.merge-request-branches & {
flex-direction: column;
}
.project_namespace {
color: $gl-text-color-secondary;
}
}
.commit-content {
......
class Admin::GeoNodesController < Admin::ApplicationController
before_action :check_license, except: [:index, :destroy]
before_action :load_node, only: [:destroy, :repair, :toggle, :status]
before_action :load_node, only: [:edit, :update, :destroy, :repair, :toggle, :status]
def index
@nodes = GeoNode.all.order(:id)
......@@ -22,6 +22,14 @@ class Admin::GeoNodesController < Admin::ApplicationController
end
end
def update
if @node.update_attributes(geo_node_params.except(:geo_node_key_attributes))
redirect_to admin_geo_nodes_path, notice: 'Geo Node was successfully updated.'
else
render 'edit'
end
end
def destroy
@node.destroy
......
......@@ -32,10 +32,10 @@ module IssuableCollections
def filter_params
set_sort_order_from_cookie
set_default_scope
set_default_state
@filter_params = params.dup
# Skip irrelevant Rails routing params
@filter_params = params.dup.except(:controller, :action, :namespace_id)
@filter_params[:sort] ||= default_sort_order
@sort = @filter_params[:sort]
......@@ -55,10 +55,6 @@ module IssuableCollections
@filter_params.permit(IssuableFinder::VALID_PARAMS)
end
def set_default_scope
params[:scope] = 'all' if params[:scope].blank?
end
def set_default_state
params[:state] = 'opened' if params[:state].blank?
end
......
module SafeMirrorParams
extend ActiveSupport::Concern
included do
helper_method :default_mirror_users
end
private
def valid_mirror_user?(mirror_params)
return true unless mirror_params[:mirror_user_id].present?
default_mirror_users.map(&:id).include?(mirror_params[:mirror_user_id].to_i)
end
def default_mirror_users
[current_user, @project.mirror_user].compact.uniq
end
end
class Dashboard::TodosController < Dashboard::ApplicationController
include ActionView::Helpers::NumberHelper
before_action :authorize_read_project!, only: :index
before_action :find_todos, only: [:index, :destroy_all]
def index
......@@ -49,6 +50,15 @@ class Dashboard::TodosController < Dashboard::ApplicationController
private
def authorize_read_project!
project_id = params[:project_id]
if project_id.present?
project = Project.find(project_id)
render_404 unless can?(current_user, :read_project, project)
end
end
def find_todos
@todos ||= TodosFinder.new(current_user, params).execute
end
......
class Projects::ImportsController < Projects::ApplicationController
include ContinueParams
include SafeMirrorParams
# Authorize
before_action :authorize_admin_project!
......@@ -11,7 +12,7 @@ class Projects::ImportsController < Projects::ApplicationController
end
def create
if @project.update_attributes(import_params)
if @project.update_attributes(safe_import_params)
@project.reload.import_schedule
end
......@@ -67,4 +68,10 @@ class Projects::ImportsController < Projects::ApplicationController
def import_params
params.require(:project).permit(:import_url, :mirror, :mirror_user_id)
end
def safe_import_params
return import_params if valid_mirror_user?(import_params)
import_params.merge(mirror_user_id: current_user.id)
end
end
class Projects::MirrorsController < Projects::ApplicationController
include RepositorySettingsRedirect
include SafeMirrorParams
# Authorize
before_action :authorize_admin_project!, except: [:update_now]
before_action :authorize_push_code!, only: [:update_now]
......@@ -12,7 +13,7 @@ class Projects::MirrorsController < Projects::ApplicationController
end
def update
if @project.update_attributes(mirror_params)
if @project.update_attributes(safe_mirror_params)
if @project.mirror?
@project.force_import_job!
......@@ -51,4 +52,10 @@ class Projects::MirrorsController < Projects::ApplicationController
params.require(:project).permit(:mirror, :import_url, :mirror_user_id,
:mirror_trigger_builds, remote_mirrors_attributes: [:url, :id, :enabled])
end
def safe_mirror_params
return mirror_params if valid_mirror_user?(mirror_params)
mirror_params.merge(mirror_user_id: current_user.id)
end
end
module Projects
module Settings
class RepositoryController < Projects::ApplicationController
include SafeMirrorParams
before_action :authorize_admin_project!
prepend ::EE::Projects::Settings::RepositoryController
......
......@@ -20,9 +20,9 @@
#
class IssuableFinder
include CreatedAtFilter
NONE = '0'.freeze
IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page].freeze
IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page state].freeze
SCALAR_PARAMS = %i(scope state group_id project_id milestone_title assignee_id search label_name sort assignee_username author_id author_username authorized_only due_date iids non_archived weight).freeze
ARRAY_PARAMS = { label_name: [], iids: [] }.freeze
......@@ -94,8 +94,14 @@ class IssuableFinder
execute.find_by!(*params)
end
def state_counter_cache_key(state)
Digest::SHA1.hexdigest(state_counter_cache_key_components(state).flatten.join('-'))
def state_counter_cache_key
cache_key(state_counter_cache_key_components)
end
def clear_caches!
state_counter_cache_key_components_permutations.each do |components|
Rails.cache.delete(cache_key(components))
end
end
def group
......@@ -447,12 +453,19 @@ class IssuableFinder
params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
end
def state_counter_cache_key_components(state)
def state_counter_cache_key_components
opts = params.with_indifferent_access
opts[:state] = state
opts.except!(*IRRELEVANT_PARAMS_FOR_CACHE_KEY)
opts.delete_if { |_, value| value.blank? }
['issuables_count', klass.to_ability_name, opts.sort]
end
def state_counter_cache_key_components_permutations
[state_counter_cache_key_components]
end
def cache_key(components)
Digest::SHA1.hexdigest(components.flatten.join('-'))
end
end
......@@ -75,7 +75,7 @@ class IssuesFinder < IssuableFinder
current_user.blank? || for_counting || params[:for_counting]
end
def state_counter_cache_key_components(state)
def state_counter_cache_key_components
extra_components = [
user_can_see_all_confidential_issues?,
user_cannot_see_confidential_issues?(for_counting: true)
......@@ -84,6 +84,16 @@ class IssuesFinder < IssuableFinder
super + extra_components
end
def state_counter_cache_key_components_permutations
# Ignore the last two, as we'll provide both options for them.
components = super.first[0..-3]
[
components + [false, true],
components + [true, false]
]
end
def by_assignee(items)
if assignee
items.assigned_to(assignee)
......
module BreadcrumbsHelper
def add_to_breadcrumbs(text, link)
@breadcrumbs_extra_links ||= []
@breadcrumbs_extra_links.push({
text: text,
link: link
})
end
def breadcrumb_title_link
return @breadcrumb_link if @breadcrumb_link
if controller.available_action?(:index)
url_for(action: "index")
else
request.path
end
end
def breadcrumb_title(title)
return if defined?(@breadcrumb_title)
@breadcrumb_title = title
end
end
......@@ -243,7 +243,7 @@ module IssuablesHelper
def issuables_count_for_state(issuable_type, state, finder: nil)
finder ||= public_send("#{issuable_type}_finder")
cache_key = finder.state_counter_cache_key(state)
cache_key = finder.state_counter_cache_key
@counts ||= {}
@counts[cache_key] ||= Rails.cache.fetch(cache_key, expires_in: 2.minutes) do
......
......@@ -4,4 +4,8 @@ module MirrorHelper
message << "<br>To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above." if can?(current_user, :push_code, @project)
message
end
def options_for_mirror_user
options_from_collection_for_select(default_mirror_users, :id, :name, @project.mirror_user_id || current_user.id)
end
end
......@@ -4,6 +4,10 @@ module PageLayoutHelper
@page_title.push(*titles.compact) if titles.any?
if show_new_nav? && titles.any? && !defined?(@breadcrumb_title)
@breadcrumb_title = @page_title.last
end
# Segments are seperated by middot
@page_title.join(" \u00b7 ")
end
......
class Geo::BaseRegistry < ActiveRecord::Base
self.abstract_class = true
if Gitlab::Geo.secondary_role_enabled? && Gitlab::Geo.geo_database_configured?
if Gitlab::Geo.geo_database_configured?
establish_connection Rails.configuration.geo_database
end
def self.connection
raise 'Geo secondary database is not configured' unless Gitlab::Geo.geo_database_configured?
super
end
end
......@@ -33,17 +33,12 @@ module Boards
end
def filter_params
set_default_scope
set_project
set_state
params
end
def set_default_scope
params[:scope] = 'all'
end
def set_project
params[:project_id] = project.id
end
......
......@@ -185,7 +185,7 @@ class IssuableBaseService < BaseService
after_create(issuable)
issuable.create_cross_references!(current_user)
execute_hooks(issuable)
invalidate_cache_counts(issuable.assignees, issuable)
invalidate_cache_counts(issuable, users: issuable.assignees)
end
issuable
......@@ -242,12 +242,12 @@ class IssuableBaseService < BaseService
old_assignees: old_assignees
)
if old_assignees != issuable.assignees
new_assignees = issuable.assignees.to_a
affected_assignees = (old_assignees + new_assignees) - (old_assignees & new_assignees)
invalidate_cache_counts(affected_assignees.compact, issuable)
end
new_assignees = issuable.assignees.to_a
affected_assignees = (old_assignees + new_assignees) - (old_assignees & new_assignees)
# Don't clear the project cache, because it will be handled by the
# appropriate service (close / reopen / merge / etc.).
invalidate_cache_counts(issuable, users: affected_assignees.compact, skip_project_cache: true)
after_update(issuable)
issuable.create_new_cross_references!(current_user)
execute_hooks(issuable, 'update')
......@@ -341,9 +341,18 @@ class IssuableBaseService < BaseService
create_labels_note(issuable, old_labels) if issuable.labels != old_labels
end
def invalidate_cache_counts(users, issuable)
def invalidate_cache_counts(issuable, users: [], skip_project_cache: false)
users.each do |user|
user.public_send("invalidate_#{issuable.model_name.singular}_cache_counts")
end
unless skip_project_cache
case issuable
when Issue
IssuesFinder.new(nil, project_id: issuable.project_id).clear_caches!
when MergeRequest
MergeRequestsFinder.new(nil, project_id: issuable.target_project_id).clear_caches!
end
end
end
end
......@@ -28,7 +28,7 @@ module Issues
notification_service.close_issue(issue, current_user) if notifications
todo_service.close_issue(issue, current_user)
execute_hooks(issue, 'close')
invalidate_cache_counts(issue.assignees, issue)
invalidate_cache_counts(issue, users: issue.assignees)
end
issue
......
......@@ -8,7 +8,7 @@ module Issues
create_note(issue)
notification_service.reopen_issue(issue, current_user)
execute_hooks(issue, 'reopen')
invalidate_cache_counts(issue.assignees, issue)
invalidate_cache_counts(issue, users: issue.assignees)
end
issue
......
......@@ -13,7 +13,7 @@ module MergeRequests
notification_service.close_mr(merge_request, current_user)
todo_service.close_merge_request(merge_request, current_user)
execute_hooks(merge_request, 'close')
invalidate_cache_counts(merge_request.assignees, merge_request)
invalidate_cache_counts(merge_request, users: merge_request.assignees)
end
merge_request
......
......@@ -13,7 +13,7 @@ module MergeRequests
create_note(merge_request)
notification_service.merge_mr(merge_request, current_user)
execute_hooks(merge_request, 'merge')
invalidate_cache_counts(merge_request.assignees, merge_request)
invalidate_cache_counts(merge_request, users: merge_request.assignees)
end
private
......
......@@ -10,7 +10,7 @@ module MergeRequests
execute_hooks(merge_request, 'reopen')
merge_request.reload_diff(current_user)
merge_request.mark_as_unchecked
invalidate_cache_counts(merge_request.assignees, merge_request)
invalidate_cache_counts(merge_request, users: merge_request.assignees)
end
merge_request
......
......@@ -3,6 +3,10 @@ class PersonalFileUploader < FileUploader
File.join(CarrierWave.root, model_path(model))
end
def self.base_dir
File.join(root_dir, 'system')
end
private
def secure_url
......
- page_title "Edit", @application.name, "Applications"
%h3.page-title Edit application
- @url = admin_application_path(@application)
= render 'form', application: @application
- breadcrumb_title "Applications"
- page_title "New Application"
%h3.page-title New application
- @url = admin_applications_path
= render 'form', application: @application
- breadcrumb_title "Messages"
- page_title "Broadcast Messages"
= render 'form'
- breadcrumb_title "Messages"
- page_title "Broadcast Messages"
%h3.page-title
......
= form_for geo_node, as: :geo_node, url: admin_geo_nodes_path, html: { class: 'form-horizontal' } do |f|
- if geo_node.errors.any?
.alert.alert-danger
- geo_node.errors.full_messages.each do |msg|
%p= msg
- disable_key_edit = local_assigns.fetch(:disable_key_edit, false)
= form_errors(geo_node)
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= form.label :primary do
= form.check_box :primary
%strong This is a primary node
.form-group
= form.label :url, 'URL', class: 'control-label'
.col-sm-10
= form.text_field :url, class: 'form-control'
= form.fields_for :geo_node_key, geo_node.geo_node_key, include_id: !disable_key_edit do |fg|
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :primary do
= f.check_box :primary
%strong This is a primary node
.form-group
= f.label :url, 'URL', class: 'control-label'
= fg.label :key, 'Public Key', class: 'control-label'
.col-sm-10
= f.text_field :url, class: 'form-control'
= f.fields_for :geo_node_key, geo_node.geo_node_key do |fg|
.form-group
= fg.label :key, 'Public Key', class: 'control-label'
.col-sm-10
= fg.text_area :key, class: 'form-control thin_area', rows: 5
= fg.text_area :key, class: 'form-control thin_area', rows: 5, disabled: disable_key_edit
- unless disable_key_edit
%p.help-block
Paste a machine public key here for the GitLab user this node runs on. Read more about how to generate it
= link_to "here", help_page_path("ssh/README")
.form-actions
= f.submit 'Add Node', class: 'btn btn-create'
%hr
- page_title 'Edit Geo Node'
%h3.page-title
Edit Geo Node
= form_for [:admin, @node], html: { class: 'form-horizontal' } do |f|
= render partial: 'form', locals: { form: f, geo_node: @node, disable_key_edit: true }
.form-actions
= f.submit 'Save changes', class: 'btn btn-create'
= link_to 'Cancel', admin_geo_nodes_path, class: 'btn btn-cancel'
%hr
......@@ -8,7 +8,13 @@
%hr
= render partial: 'form', locals: {geo_node: @node} if Gitlab::Geo.license_allows?
- if Gitlab::Geo.license_allows?
= form_for [:admin, @node], as: :geo_node, url: admin_geo_nodes_path, html: { class: 'form-horizontal' } do |f|
= render partial: 'form', locals: { form: f, geo_node: @node }
.form-actions
= f.submit 'Add Node', class: 'btn btn-create'
%hr
- if @nodes.any?
.panel.panel-default
......@@ -52,11 +58,12 @@
%p
.js-health
- if Gitlab::Geo.primary?
- unless Gitlab::Geo.secondary?
.node-actions
- if Gitlab::Geo.license_allows?
- if node.missing_oauth_application?
= link_to "Repair authentication", repair_admin_geo_node_path(node), method: :post, title: 'OAuth application is missing', class: 'btn btn-default btn-sm'
- if node.secondary?
= toggle_node_button(node)
= link_to "Edit", edit_admin_geo_node_path(node), class: 'btn btn-sm'
= link_to "Remove", admin_geo_node_path(node), data: { confirm: 'Are you sure?' }, method: :delete, class: 'btn btn-remove btn-sm'
- if show_new_nav? && current_user.can_create_group?
- content_for :breadcrumbs_extra do
= link_to "New group", new_group_path, class: "btn btn-new"
.top-area
%ul.nav-links
= nav_link(page: dashboard_groups_path) do
......@@ -6,9 +10,8 @@
= nav_link(page: explore_groups_path) do
= link_to explore_groups_path, title: 'Explore public groups' do
Explore public groups
.nav-controls
.nav-controls{ class: ("nav-controls-new-nav" if show_new_nav?) }
= render 'shared/groups/search_form'
= render 'shared/groups/dropdown'
- if current_user.can_create_group?
= link_to new_group_path, class: "btn btn-new" do
New group
= link_to "New group", new_group_path, class: "btn btn-new #{("visible-xs" if show_new_nav?)}"
= content_for :flash_message do
= render 'shared/project_limit'
- if show_new_nav? && current_user.can_create_project?
- content_for :breadcrumbs_extra do
= link_to "New project", new_project_path, class: 'btn btn-new'
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
......@@ -14,9 +19,8 @@
= link_to explore_root_path, title: 'Explore', data: {placement: 'right'} do
Explore projects
.nav-controls
.nav-controls{ class: ("nav-controls-new-nav" if show_new_nav?) }
= render 'shared/projects/search_form'
= render 'shared/projects/dropdown'
- if current_user.can_create_project?
= link_to new_project_path, class: 'btn btn-new' do
New project
= link_to "New project", new_project_path, class: "btn btn-new #{("visible-xs" if show_new_nav?)}"
- if show_new_nav? && current_user
- content_for :breadcrumbs_extra do
= link_to "New snippet", new_snippet_path, class: "btn btn-new", title: "New snippet"
.top-area
%ul.nav-links
= nav_link(page: dashboard_snippets_path, html_options: {class: 'home'}) do
......@@ -8,6 +12,5 @@
Explore Snippets
- if current_user
.nav-controls.hidden-xs
= link_to new_snippet_path, class: "btn btn-new", title: "New snippet" do
New snippet
.nav-controls.hidden-xs{ class: ("hidden-sm hidden-md hidden-lg" if show_new_nav?) }
= link_to "New snippet", new_snippet_path, class: "btn btn-new", title: "New snippet"
- @hide_top_links = true
- page_title "Issues"
- header_title "Issues", issues_dashboard_path(assignee_id: current_user.id)
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{current_user.name} issues")
- if show_new_nav?
- content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do
= icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
.top-area
= render 'shared/issuable/nav', type: :issues
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do
= icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
......
- @hide_top_links = true
- page_title "Merge Requests"
- header_title "Merge Requests", merge_requests_dashboard_path(assignee_id: current_user.id)
- if show_new_nav?
- content_for :breadcrumbs_extra do
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
.top-area
= render 'shared/issuable/nav', type: :merge_requests
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
= render 'shared/issuable/filter', type: :merge_requests
......
......@@ -2,10 +2,14 @@
- page_title 'Milestones'
- header_title 'Milestones', dashboard_milestones_path
- if show_new_nav?
- content_for :breadcrumbs_extra do
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
.top-area
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
.milestones
......
- @no_container = true
- @hide_top_links = true
- @breadcrumb_title = "Projects"
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
......
- @hide_top_links = true
- @no_container = true
- breadcrumb_title "Projects"
- page_title "Starred Projects"
- header_title "Projects", dashboard_projects_path
......
- @hide_top_links = true
- page_title "Todos"
- header_title "Todos", dashboard_todos_path
......
- @hide_top_links = true
- page_title "Groups"
- header_title "Groups", dashboard_groups_path
......
- @hide_top_links = true
- page_title "Projects"
- header_title "Projects", dashboard_projects_path
......
- @hide_top_links = true
- page_title "Projects"
- header_title "Projects", dashboard_projects_path
......
- @hide_top_links = true
- page_title "Projects"
- header_title "Projects", dashboard_projects_path
......
- @hide_top_links = true
- page_title "Snippets"
- header_title "Snippets", snippets_path
......
- page_title "Issues"
- group_issues_exists = group_issues(@group).exists?
= render "head_issues"
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@group.name} issues")
- if group_issues(@group).exists?
- if show_new_nav? && group_issues_exists
- content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do
= icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue"
- if group_issues_exists
.top-area
= render 'shared/issuable/nav', type: :issues
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= link_to params.merge(rss_url_options), class: 'btn' do
= icon('rss')
%span.icon-label
......
- page_title 'Labels'
- if show_new_nav? && can?(current_user, :admin_label, @group)
- content_for :breadcrumbs_extra do
= link_to "New label", new_group_label_path(@group), class: "btn btn-new"
= render "groups/head_issues"
.top-area.adjust
.nav-text
Labels can be applied to issues and merge requests. Group labels are available for any project within the group.
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- if can?(current_user, :admin_label, @group)
= link_to new_group_label_path(@group), class: "btn btn-new" do
New label
= link_to "New label", new_group_label_path(@group), class: "btn btn-new"
.labels
.other-labels
......
- breadcrumb_title "Labels"
- page_title 'New Label'
- header_title group_title(@group, 'Labels', group_labels_path(@group))
......
- page_title "Merge Requests"
- if show_new_nav? && current_user
- content_for :breadcrumbs_extra do
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
- if @group_merge_requests.empty?
= render 'shared/empty_states/merge_requests', project_select_button: true
- else
.top-area
= render 'shared/issuable/nav', type: :merge_requests
- if current_user
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
= render 'shared/issuable/filter', type: :merge_requests
......
- page_title "Milestones"
- if show_new_nav? && can?(current_user, :admin_milestones, @group)
- content_for :breadcrumbs_extra do
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new"
= render "groups/head_issues"
.top-area
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- if can?(current_user, :admin_milestones, @group)
= link_to new_group_milestone_path(@group), class: "btn btn-new" do
New milestone
= link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new"
.milestones
%ul.content-list
......
- breadcrumb_title "Milestones"
- page_title "Milestones"
- header_title group_title(@group, "Milestones", group_milestones_path(@group))
......
- @breadcrumb_link = dashboard_groups_path
- breadcrumb_title "Groups"
- @hide_top_links = true
- page_title 'New Group'
- header_title "Groups", dashboard_groups_path
......
- @no_container = true
- breadcrumb_title "Group"
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
......
......@@ -15,7 +15,8 @@
- if show_new_nav?
- if content_for?(:new_global_flash)
= yield :new_global_flash
= render "layouts/nav/breadcrumbs"
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
= render "layouts/flash"
= yield :flash_message
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
......
- breadcrumb_title = @breadcrumb_title || controller.controller_name.humanize
- breadcrumb_link = breadcrumb_title_link
- hide_top_links = @hide_top_links || false
%nav.breadcrumbs{ role: "navigation" }
......@@ -8,12 +8,16 @@
.title
= link_to "GitLab", root_path
\/
- if content_for?(:header_title_before)
= yield :header_title_before
\/
= header_title
%h2.breadcrumbs-sub-title
%ul.list-unstyled
- if content_for?(:sub_title_before)
= yield :sub_title_before
%li= link_to breadcrumb_title, request.path
- if @breadcrumbs_extra_links
- @breadcrumbs_extra_links.each do |extra|
%li= link_to extra[:text], extra[:link]
%li= link_to @breadcrumb_title, breadcrumb_link
- if content_for?(:breadcrumbs_extra)
.breadcrumbs-extra.hidden-xs= yield :breadcrumbs_extra
= yield :header_content
......@@ -13,7 +13,7 @@
= nav_link(controller: :dashboard, html_options: {class: 'home'}) do
= link_to admin_root_path, title: 'Overview' do
%span
Overview
Dashboard
= nav_link(controller: [:admin, :projects]) do
= link_to admin_projects_path, title: 'Projects' do
%span
......
......@@ -3,7 +3,7 @@
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
Projects
= nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= nav_link(controller: ['dashboard/groups', 'explore/groups']) do
= link_to dashboard_groups_path, class: 'dashboard-shortcuts-groups', title: 'Groups' do
Groups
......
- breadcrumb_title "Profile"
- @content_class = "limit-container-width" unless fluid_layout
= render 'profiles/head'
......
- page_title 'Two-Factor Authentication', 'Account'
- header_title "Two-Factor Authentication", profile_two_factor_auth_path
- if show_new_nav?
- add_to_breadcrumbs("Account", profile_account_path)
- else
- header_title "Two-Factor Authentication", profile_two_factor_auth_path
- @content_class = "limit-container-width" unless fluid_layout
= render 'profiles/head'
- if inject_u2f_api?
......
- @no_container = true
- if show_new_nav?
- add_to_breadcrumbs("Project", project_path(@project))
- page_title "Activity"
= render "projects/head"
......
- breadcrumb_title "Repository"
- @no_container = true
- page_title "Edit", @blob.path, @ref
- content_for :page_specific_javascripts do
......
- breadcrumb_title "Repository"
- page_title "New File", @path.presence, @ref
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js')
......
- breadcrumb_title "Repository"
- @no_container = true
- page_title @blob.path, @ref
......
......@@ -4,8 +4,7 @@
- page_title "Boards"
- if show_new_nav?
- content_for :sub_title_before do
%li= link_to "Issues", project_issues_path(@project)
- add_to_breadcrumbs("Issues", project_issues_path(@project))
- content_for :page_specific_javascripts do
= webpack_bundle_tag 'common_vue'
......
......@@ -2,6 +2,9 @@
- page_title "Branches"
= render "projects/commits/head"
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
%div{ class: container_class }
.top-area.adjust
.nav-text
......
- ref = local_assigns.fetch(:ref)
- show_project_name = local_assigns.fetch(:show_project_name, false)
- if @note_counts
- note_count = @note_counts.fetch(commit.id, 0)
- else
......@@ -34,6 +35,9 @@
- commit_timeago = time_ago_with_tooltip(commit.committed_date)
- commit_text = _('%{commit_author_link} committed %{commit_timeago}') % { commit_author_link: commit_author_link, commit_timeago: commit_timeago }
#{ commit_text.html_safe }
- if show_project_name
%span.project_namespace
= project.name_with_namespace
.commit-actions.flex-row.hidden-xs
......
- @no_container = true
- breadcrumb_title _("Commits")
- page_title _("Commits"), @ref
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits")
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
= content_for :sub_nav do
= render "head"
......
- @no_container = true
- page_title "Compare"
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
= render "projects/commits/head"
%div{ class: container_class }
......
- @no_container = true
- breadcrumb_title "Compare"
- page_title "#{params[:from]}...#{params[:to]}"
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
= render "projects/commits/head"
%div{ class: container_class }
......
- @no_container = true
- page_title "Cycle Analytics"
- if show_new_nav?
- add_to_breadcrumbs("Project", project_path(@project))
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('cycle_analytics')
......
......@@ -2,6 +2,9 @@
- page_title "Environments"
= render "projects/pipelines/head"
- if show_new_nav?
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag("environments")
......
- @no_container = true
- breadcrumb_title "Environments"
- page_title 'New Environment'
= render "projects/pipelines/head"
......
- @no_container = true
- page_title "Charts"
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('graphs')
......
......@@ -3,6 +3,10 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('graphs')
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
= render 'projects/commits/head'
%div{ class: container_class }
......
- breadcrumb_title "Issues"
- page_title "New Issue"
%h3.page-title
......
......@@ -2,6 +2,9 @@
- page_title "Jobs"
= render "projects/pipelines/head"
- if show_new_nav?
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
%div{ class: container_class }
.top-area
- build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) }
......
- @no_container = true
- page_title "Labels"
- hide_class = ''
- if show_new_nav? && can?(current_user, :admin_label, @project)
- content_for :breadcrumbs_extra do
= link_to "New label", new_namespace_project_label_path(@project.namespace, @project), class: "btn btn-new"
= render "shared/mr_head"
- if @labels.exists? || @prioritized_labels.exists?
......@@ -9,7 +14,7 @@
.nav-text
Labels can be applied to issues and merge requests. Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- if can?(current_user, :admin_label, @project)
= link_to new_project_label_path(@project), class: "btn btn-new" do
New label
......
- @no_container = true
- breadcrumb_title "Labels"
- page_title "New Label"
= render "shared/mr_head"
......
- breadcrumb_title "Merge Requests"
- page_title "New Merge Request"
- if @merge_request.can_be_created && !params[:change_branches]
......
- @no_container = true
- page_title 'Milestones'
- if show_new_nav?
- content_for :breadcrumbs_extra do
= link_to "New milestone", new_namespace_project_milestone_path(@project.namespace, @project), class: 'btn btn-new', title: 'New milestone'
= render "shared/mr_head"
%div{ class: container_class }
......
- @no_container = true
- breadcrumb_title "Milestones"
- page_title "New Milestone"
= render "shared/mr_head"
......
......@@ -36,12 +36,11 @@
= render "projects/mirrors/instructions"
.form-group
= f.label :mirror_user_id, "Mirror user", class: "label-light"
= users_select_tag("project[mirror_user_id]", class: 'input-large', selected: @project.mirror_user_id || current_user.id,
first_user: true, current_user: true, push_code_to_protected_branches: true)
= select_tag('project[mirror_user_id]', options_for_mirror_user, class: "select2 lg", required: true)
.help-block
This user will be the author of all events in the activity feed that are the result of an update,
like new branches being created or new commits being pushed to existing branches.
They need to have at least master access to this project.
You can only assign yourself to be the mirror user.
- if @project.builds_enabled?
= render "shared/mirror_trigger_builds_setting", f: f
= f.submit 'Save changes', class: 'btn btn-create', name: 'update_remote_mirror'
......
- breadcrumb_title "Graph"
- page_title "Graph", @ref
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('network')
- if show_new_nav?
- add_to_breadcrumbs("Repository", project_tree_path(@project))
= render "projects/commits/head"
= render "head"
%div{ class: container_class }
......
- @breadcrumb_link = dashboard_projects_path
- breadcrumb_title "Projects"
- @hide_top_links = true
- page_title 'New Project'
- header_title "Projects", dashboard_projects_path
- visibility_level = params.dig(:project, :visibility_level) || default_project_visibility
......
- breadcrumb_title "Schedules"
- content_for :page_specific_javascripts do
= webpack_bundle_tag 'common_vue'
= webpack_bundle_tag 'schedules_index'
- @no_container = true
- page_title _("Pipeline Schedules")
- if show_new_nav? && can?(current_user, :create_pipeline_schedule, @project)
- content_for :breadcrumbs_extra do
= link_to _('New schedule'), new_namespace_project_pipeline_schedule_path(@project.namespace, @project), class: 'btn btn-create'
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
= render "projects/pipelines/head"
%div{ class: container_class }
......@@ -13,7 +22,7 @@
= render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope
- if can?(current_user, :create_pipeline_schedule, @project)
.nav-controls
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-create' do
%span= _('New schedule')
......
- breadcrumb_title "Schedules"
- @breadcrumb_link = namespace_project_pipeline_schedules_path(@project.namespace, @project)
- page_title _("New Pipeline Schedule")
- if show_new_nav?
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
%h3.page-title
= _("Schedule a new pipeline")
%hr
......
- @no_container = true
- page_title _("Charts"), _("Pipelines")
- if show_new_nav?
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_d3')
= page_specific_javascript_bundle_tag('graphs')
......
- breadcrumb_title "Pipelines"
- page_title "New Pipeline"
%h3.page-title
......
- page_title "Members"
- if show_new_nav?
- add_to_breadcrumbs("Settings", edit_project_path(@project))
.row.prepend-top-default
.col-lg-12
%h4
......
- breadcrumb_title "Integrations"
- page_title @service.title, "Services"
- if show_new_nav?
- add_to_breadcrumbs("Settings", edit_project_path(@project))
= render "projects/settings/head"
= render 'form'
- @content_class = "limit-container-width" unless fluid_layout
- page_title "Pipelines"
- if show_new_nav?
- add_to_breadcrumbs("Settings", edit_project_path(@project))
= render "projects/settings/head"
= render 'projects/runners/index'
......
- @content_class = "limit-container-width" unless fluid_layout
- page_title 'Integrations'
- if show_new_nav?
- add_to_breadcrumbs("Settings", edit_project_path(@project))
= render "projects/settings/head"
= render 'projects/hooks/index'
= render 'projects/services/index'
- page_title "Repository"
- @content_class = "limit-container-width" unless fluid_layout
- if show_new_nav?
- add_to_breadcrumbs("Settings", edit_project_path(@project))
= render "projects/settings/head"
- content_for :page_specific_javascripts do
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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