Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq
This commit is contained in:
commit
a69855fc90
23 changed files with 189 additions and 17 deletions
|
@ -41,6 +41,8 @@ v 7.13.0 (unreleased)
|
||||||
- Allow users to be blocked and unblocked via the API
|
- Allow users to be blocked and unblocked via the API
|
||||||
- Use native Postgres database cleaning during backup restore
|
- Use native Postgres database cleaning during backup restore
|
||||||
- Redesign project page. Show README as default instead of activity. Move project activity to separate page
|
- Redesign project page. Show README as default instead of activity. Move project activity to separate page
|
||||||
|
- Make left menu more hierarchical and less contextual by adding back item at top
|
||||||
|
- A fork can’t have a visibility level that is greater than the original project.
|
||||||
|
|
||||||
v 7.12.2
|
v 7.12.2
|
||||||
- Correctly show anonymous authorized applications under Profile > Applications.
|
- Correctly show anonymous authorized applications under Profile > Applications.
|
||||||
|
|
|
@ -39,12 +39,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
padding: 7px 15px;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
color: $gray;
|
color: $gray;
|
||||||
display: block;
|
display: block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 8px 15px;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 20px;
|
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -114,9 +114,6 @@
|
||||||
width: $sidebar_collapsed_width;
|
width: $sidebar_collapsed_width;
|
||||||
|
|
||||||
li a {
|
li a {
|
||||||
font-size: 14px;
|
|
||||||
padding: 8px 15px;
|
|
||||||
text-align: left;
|
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ module GitlabMarkdownHelper
|
||||||
|
|
||||||
# Returns a random markdown tip for use as a textarea placeholder
|
# Returns a random markdown tip for use as a textarea placeholder
|
||||||
def random_markdown_tip
|
def random_markdown_tip
|
||||||
"Tip: #{MARKDOWN_TIPS.sample}"
|
MARKDOWN_TIPS.sample
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -92,6 +92,16 @@ module ProjectsHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can_change_visibility_level?(project, current_user)
|
||||||
|
return false unless can?(current_user, :change_visibility_level, project)
|
||||||
|
|
||||||
|
if project.forked?
|
||||||
|
project.forked_from_project.visibility_level > Gitlab::VisibilityLevel::PRIVATE
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def get_project_nav_tabs(project, current_user)
|
def get_project_nav_tabs(project, current_user)
|
||||||
|
|
|
@ -86,4 +86,10 @@ module VisibilityLevelHelper
|
||||||
def default_snippet_visibility
|
def default_snippet_visibility
|
||||||
current_application_settings.default_snippet_visibility
|
current_application_settings.default_snippet_visibility
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def skip_level?(form_model, level)
|
||||||
|
form_model.is_a?(Project) &&
|
||||||
|
form_model.forked? &&
|
||||||
|
!Gitlab::VisibilityLevel.allowed_fork_levels(form_model.forked_from_project.visibility_level).include?(level)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
- if event.created_project?
|
- if event.created_project?
|
||||||
= cache [event, current_user] do
|
= cache [event, current_user] do
|
||||||
|
= image_tag avatar_icon(event.author_email, 24), class: "avatar s24", alt:''
|
||||||
= render "events/event/created_project", event: event
|
= render "events/event/created_project", event: event
|
||||||
- else
|
- else
|
||||||
= cache event do
|
= cache event do
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
%ul.nav.nav-sidebar
|
%ul.nav.nav-sidebar
|
||||||
|
= nav_link do
|
||||||
|
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'} do
|
||||||
|
= icon('caret-square-o-left fw')
|
||||||
|
%span
|
||||||
|
Back to Dashboard
|
||||||
|
|
||||||
|
%li.separate-item
|
||||||
|
|
||||||
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do
|
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do
|
||||||
= link_to group_path(@group), title: 'Home', data: {placement: 'right'} do
|
= link_to group_path(@group), title: 'Home', data: {placement: 'right'} do
|
||||||
= icon('dashboard fw')
|
= icon('dashboard fw')
|
||||||
%span
|
%span
|
||||||
Activity
|
Group
|
||||||
- if current_user
|
- if current_user
|
||||||
= nav_link(controller: [:group, :milestones]) do
|
= nav_link(controller: [:group, :milestones]) do
|
||||||
= link_to group_milestones_path(@group), title: 'Milestones', data: {placement: 'right'} do
|
= link_to group_milestones_path(@group), title: 'Milestones', data: {placement: 'right'} do
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
%ul.nav.nav-sidebar
|
%ul.nav.nav-sidebar
|
||||||
|
= nav_link do
|
||||||
|
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'} do
|
||||||
|
= icon('caret-square-o-left fw')
|
||||||
|
%span
|
||||||
|
Back to Dashboard
|
||||||
|
|
||||||
|
%li.separate-item
|
||||||
|
|
||||||
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
|
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
|
||||||
= link_to profile_path, title: 'Profile', data: {placement: 'right'} do
|
= link_to profile_path, title: 'Profile', data: {placement: 'right'} do
|
||||||
= icon('user fw')
|
= icon('user fw')
|
||||||
|
|
|
@ -1,4 +1,19 @@
|
||||||
%ul.nav.nav-sidebar
|
%ul.nav.nav-sidebar
|
||||||
|
- if @project.group
|
||||||
|
= nav_link do
|
||||||
|
= link_to group_path(@project.group), title: 'Back to group', data: {placement: 'right'} do
|
||||||
|
= icon('caret-square-o-left fw')
|
||||||
|
%span
|
||||||
|
Back to Group
|
||||||
|
- else
|
||||||
|
= nav_link do
|
||||||
|
= link_to root_path, title: 'Back to dashboard', data: {placement: 'right'} do
|
||||||
|
= icon('caret-square-o-left fw')
|
||||||
|
%span
|
||||||
|
Back to Dashboard
|
||||||
|
|
||||||
|
%li.separate-item
|
||||||
|
|
||||||
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do
|
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do
|
||||||
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do
|
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project', data: {placement: 'right'} do
|
||||||
= icon('home fw')
|
= icon('home fw')
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
%input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }
|
%input#zen-toggle-comment.zen-toggle-comment{ tabindex: '-1', type: 'checkbox' }
|
||||||
.zen-backdrop
|
.zen-backdrop
|
||||||
- classes << ' js-gfm-input markdown-area'
|
- classes << ' js-gfm-input markdown-area'
|
||||||
= f.text_area attr, class: classes, placeholder: random_markdown_tip
|
= f.text_area attr, class: classes, placeholder: ''
|
||||||
= link_to nil, class: 'zen-enter-link', tabindex: '-1' do
|
= link_to nil, class: 'zen-enter-link', tabindex: '-1' do
|
||||||
%i.fa.fa-expand
|
%i.fa.fa-expand
|
||||||
Edit in fullscreen
|
Edit in fullscreen
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
.col-sm-10= f.select(:default_branch, @repository.branch_names, {}, {class: 'select2 select-wide'})
|
.col-sm-10= f.select(:default_branch, @repository.branch_names, {}, {class: 'select2 select-wide'})
|
||||||
|
|
||||||
|
|
||||||
= render 'shared/visibility_level', f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can?(current_user, :change_visibility_level, @project), form_model: @project
|
= render 'shared/visibility_level', f: f, visibility_level: @project.visibility_level, can_change_visibility_level: can_change_visibility_level?(@project, current_user), form_model: @project
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
= f.label :tag_list, "Tags", class: 'control-label'
|
= f.label :tag_list, "Tags", class: 'control-label'
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
= pluralize label.open_issues_count, 'open issue'
|
= pluralize label.open_issues_count, 'open issue'
|
||||||
|
|
||||||
- if can? current_user, :admin_label, @project
|
- if can? current_user, :admin_label, @project
|
||||||
= link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn'
|
= link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm'
|
||||||
= link_to 'Remove', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
|
= link_to 'Remove', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field'
|
= render 'projects/zen', f: f, attr: :note, classes: 'note_text js-note-text js-task-list-field'
|
||||||
|
|
||||||
.comment-hints.clearfix
|
.comment-hints.clearfix
|
||||||
.pull-left Comments are parsed with #{link_to 'GitLab Flavored Markdown', help_page_path('markdown', 'markdown'),{ target: '_blank', tabindex: -1 }}
|
.pull-left #{link_to 'Markdown ', help_page_path('markdown', 'markdown'),{ target: '_blank', tabindex: -1 }}
|
||||||
.pull-right Attach files by dragging & dropping or #{link_to 'selecting them', '#', class: 'markdown-selector', tabindex: -1 }.
|
.pull-right #{link_to 'Attach a file', '#', class: 'markdown-selector', tabindex: -1 }
|
||||||
|
|
||||||
.note-form-actions
|
.note-form-actions
|
||||||
.buttons
|
.buttons
|
||||||
|
|
|
@ -12,8 +12,14 @@
|
||||||
classes: 'note_text js-note-text'
|
classes: 'note_text js-note-text'
|
||||||
|
|
||||||
.comment-hints.clearfix
|
.comment-hints.clearfix
|
||||||
.pull-left Comments are parsed with #{link_to "GitLab Flavored Markdown", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }}
|
.pull-left
|
||||||
.pull-right Attach files by dragging & dropping or #{link_to "selecting them", '#', class: 'markdown-selector', tabindex: -1 }.
|
= link_to "Markdown ", help_page_path("markdown", "markdown"),{ target: '_blank', tabindex: -1 }
|
||||||
|
tip:
|
||||||
|
= random_markdown_tip
|
||||||
|
.pull-right
|
||||||
|
= link_to '#', class: 'markdown-selector', tabindex: -1 do
|
||||||
|
Attach a file
|
||||||
|
= icon('paperclip')
|
||||||
.error-alert
|
.error-alert
|
||||||
|
|
||||||
.note-form-actions
|
.note-form-actions
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
- Gitlab::VisibilityLevel.values.each do |level|
|
- Gitlab::VisibilityLevel.values.each do |level|
|
||||||
|
- next if skip_level?(form_model, level)
|
||||||
.radio
|
.radio
|
||||||
- restricted = restricted_visibility_levels.include?(level)
|
- restricted = restricted_visibility_levels.include?(level)
|
||||||
= form.label "#{model_method}_#{level}" do
|
= form.label "#{model_method}_#{level}" do
|
||||||
|
|
|
@ -4,6 +4,10 @@ Feature: Groups
|
||||||
And "John Doe" is owner of group "Owned"
|
And "John Doe" is owner of group "Owned"
|
||||||
And "John Doe" is guest of group "Guest"
|
And "John Doe" is guest of group "Guest"
|
||||||
|
|
||||||
|
Scenario: I should have back to group button
|
||||||
|
When I visit group "Owned" page
|
||||||
|
Then I should see back to dashboard button
|
||||||
|
|
||||||
@javascript
|
@javascript
|
||||||
Scenario: I should see group "Owned" dashboard list
|
Scenario: I should see group "Owned" dashboard list
|
||||||
When I visit group "Owned" page
|
When I visit group "Owned" page
|
||||||
|
|
|
@ -18,6 +18,15 @@ Feature: Project
|
||||||
Then I should see the default project avatar
|
Then I should see the default project avatar
|
||||||
And I should not see the "Remove avatar" button
|
And I should not see the "Remove avatar" button
|
||||||
|
|
||||||
|
Scenario: I should have back to group button
|
||||||
|
And project "Shop" belongs to group
|
||||||
|
And I visit project "Shop" page
|
||||||
|
Then I should see back to group button
|
||||||
|
|
||||||
|
Scenario: I should have back to group button
|
||||||
|
And I visit project "Shop" page
|
||||||
|
Then I should see back to dashboard button
|
||||||
|
|
||||||
Scenario: I should have readme on page
|
Scenario: I should have readme on page
|
||||||
And I visit project "Shop" page
|
And I visit project "Shop" page
|
||||||
Then I should see project "Shop" README
|
Then I should see project "Shop" README
|
||||||
|
|
|
@ -5,6 +5,10 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
|
||||||
include SharedUser
|
include SharedUser
|
||||||
include Select2Helper
|
include Select2Helper
|
||||||
|
|
||||||
|
step 'I should see back to dashboard button' do
|
||||||
|
expect(page).to have_content 'Back to Dashboard'
|
||||||
|
end
|
||||||
|
|
||||||
step 'gitlab user "Mike"' do
|
step 'gitlab user "Mike"' do
|
||||||
create(:user, name: "Mike")
|
create(:user, name: "Mike")
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,4 +116,18 @@ class Spinach::Features::Project < Spinach::FeatureSteps
|
||||||
step 'I should not see "Snippets" button' do
|
step 'I should not see "Snippets" button' do
|
||||||
expect(page).not_to have_link 'Snippets'
|
expect(page).not_to have_link 'Snippets'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
step 'project "Shop" belongs to group' do
|
||||||
|
group = create(:group)
|
||||||
|
@project.namespace = group
|
||||||
|
@project.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
step 'I should see back to dashboard button' do
|
||||||
|
expect(page).to have_content 'Back to Dashboard'
|
||||||
|
end
|
||||||
|
|
||||||
|
step 'I should see back to group button' do
|
||||||
|
expect(page).to have_content 'Back to Group'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,6 +47,10 @@ module Gitlab
|
||||||
def valid_level?(level)
|
def valid_level?(level)
|
||||||
options.has_value?(level)
|
options.has_value?(level)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def allowed_fork_levels(origin_level)
|
||||||
|
[PRIVATE, INTERNAL, PUBLIC].select{ |level| level <= origin_level }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def private?
|
def private?
|
||||||
|
|
|
@ -137,7 +137,7 @@ describe GitlabMarkdownHelper do
|
||||||
describe 'random_markdown_tip' do
|
describe 'random_markdown_tip' do
|
||||||
it 'returns a random Markdown tip' do
|
it 'returns a random Markdown tip' do
|
||||||
stub_const("#{described_class}::MARKDOWN_TIPS", ['Random tip'])
|
stub_const("#{described_class}::MARKDOWN_TIPS", ['Random tip'])
|
||||||
expect(random_markdown_tip).to eq 'Tip: Random tip'
|
expect(random_markdown_tip).to eq 'Random tip'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,4 +8,48 @@ describe ProjectsHelper do
|
||||||
expect(project_status_css_class("finished")).to eq("success")
|
expect(project_status_css_class("finished")).to eq("success")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "can_change_visibility_level?" do
|
||||||
|
let(:project) { create(:project) }
|
||||||
|
|
||||||
|
let(:fork_project) do
|
||||||
|
fork_project = create(:forked_project_with_submodules)
|
||||||
|
fork_project.build_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id)
|
||||||
|
fork_project.save
|
||||||
|
|
||||||
|
fork_project
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:user) { create(:user) }
|
||||||
|
|
||||||
|
it "returns false if there are no approipriate permissions" do
|
||||||
|
allow(helper).to receive(:can?) { false }
|
||||||
|
|
||||||
|
expect(helper.can_change_visibility_level?(project, user)).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if there are permissions and it is not fork" do
|
||||||
|
allow(helper).to receive(:can?) { true }
|
||||||
|
|
||||||
|
expect(helper.can_change_visibility_level?(project, user)).to be_truthy
|
||||||
|
end
|
||||||
|
|
||||||
|
context "forks" do
|
||||||
|
it "returns false if there are permissions and origin project is PRIVATE" do
|
||||||
|
allow(helper).to receive(:can?) { true }
|
||||||
|
|
||||||
|
project.update visibility_level: Gitlab::VisibilityLevel::PRIVATE
|
||||||
|
|
||||||
|
expect(helper.can_change_visibility_level?(fork_project, user)).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true if there are permissions and origin project is INTERNAL" do
|
||||||
|
allow(helper).to receive(:can?) { true }
|
||||||
|
|
||||||
|
project.update visibility_level: Gitlab::VisibilityLevel::INTERNAL
|
||||||
|
|
||||||
|
expect(helper.can_change_visibility_level?(fork_project, user)).to be_truthy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -72,4 +72,43 @@ describe VisibilityLevelHelper do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "skip_level?" do
|
||||||
|
describe "forks" do
|
||||||
|
let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
|
||||||
|
let(:fork_project) { create(:forked_project_with_submodules) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
fork_project.build_forked_project_link(forked_to_project_id: fork_project.id, forked_from_project_id: project.id)
|
||||||
|
fork_project.save
|
||||||
|
end
|
||||||
|
|
||||||
|
it "skips levels" do
|
||||||
|
expect(skip_level?(fork_project, Gitlab::VisibilityLevel::PUBLIC)).to be_truthy
|
||||||
|
expect(skip_level?(fork_project, Gitlab::VisibilityLevel::INTERNAL)).to be_falsey
|
||||||
|
expect(skip_level?(fork_project, Gitlab::VisibilityLevel::PRIVATE)).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "non-forked project" do
|
||||||
|
let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
|
||||||
|
|
||||||
|
it "skips levels" do
|
||||||
|
expect(skip_level?(project, Gitlab::VisibilityLevel::PUBLIC)).to be_falsey
|
||||||
|
expect(skip_level?(project, Gitlab::VisibilityLevel::INTERNAL)).to be_falsey
|
||||||
|
expect(skip_level?(project, Gitlab::VisibilityLevel::PRIVATE)).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Snippet" do
|
||||||
|
let(:snippet) { create(:snippet, visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
|
||||||
|
|
||||||
|
it "skips levels" do
|
||||||
|
expect(skip_level?(snippet, Gitlab::VisibilityLevel::PUBLIC)).to be_falsey
|
||||||
|
expect(skip_level?(snippet, Gitlab::VisibilityLevel::INTERNAL)).to be_falsey
|
||||||
|
expect(skip_level?(snippet, Gitlab::VisibilityLevel::PRIVATE)).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue