Commit 16ca3ee6 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'project-navigation-redesign' into 'master'

Project navigation redesign

Based on !3980. Part of #14838. This MR targets on desktop version. Mobile version improvements will be in separate merge request.

Part of #17522

cc @jschatz1 

See merge request !4053
parents 438b186a 510b5c5f
Please view this file on the master branch, on stable branches it's out of date.
v 8.9.0 (unreleased)
- Redesign navigation for project pages
v 8.8.2 (unreleased)
- Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources
......
......@@ -119,7 +119,7 @@ class Dispatcher
new UsersSelect()
when 'projects'
new NamespaceSelect()
when 'dashboard'
when 'dashboard', 'root'
shortcut_handler = new ShortcutsDashboardNavigation()
when 'profiles'
new Profile()
......
......@@ -3,10 +3,10 @@
class @ShortcutsDashboardNavigation extends Shortcuts
constructor: ->
super()
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-activity'))
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-issues'))
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-merge_requests'))
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-projects'))
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-activity'))
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-issues'))
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-merge_requests'))
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-projects'))
@findAndFollowLink: (selector) ->
link = $(selector).attr('href')
......
......@@ -45,6 +45,7 @@
&.s32 { font-size: 20px; line-height: 32px; }
&.s40 { font-size: 16px; line-height: 40px; }
&.s60 { font-size: 32px; line-height: 60px; }
&.s70 { font-size: 34px; line-height: 70px; }
&.s90 { font-size: 36px; line-height: 90px; }
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
&.s140 { font-size: 72px; line-height: 140px; }
......
......@@ -24,8 +24,8 @@
background-color: $background-color;
padding: $gl-padding;
margin-bottom: 0;
border-top: 1px solid $border-color;
border-bottom: 1px solid $border-color;
border-top: 1px solid $white-dark;
border-bottom: 1px solid $white-dark;
color: $gl-gray;
&.oneline-block {
......@@ -110,9 +110,9 @@
.cover-title {
color: $gl-header-color;
margin: 0;
font-size: 23px;
font-size: 24px;
font-weight: normal;
margin: 16px 0 5px;
margin-bottom: 5px;
color: #4c4e54;
font-size: 23px;
line-height: 1.1;
......@@ -137,7 +137,6 @@
}
.cover-desc {
padding: 0 $gl-padding 3px;
color: $gl-text-color;
&.username:last-child {
......@@ -205,7 +204,7 @@
.content-block {
padding: $gl-padding 0;
border-bottom: 1px solid $border-color;
border-bottom: 1px solid $white-dark;
&.oneline-block {
line-height: 36px;
......
......@@ -48,10 +48,6 @@
display: block;
}
.project-home-desc {
font-size: 21px;
}
.project-repo-buttons,
.git-clone-holder {
display: none;
......
......@@ -196,7 +196,7 @@
position: fixed;
top: $header-height;
width: 100%;
z-index: 1;
z-index: 3;
background: $background-color;
border-bottom: 1px solid $border-color;
transition-duration: .3s;
......@@ -238,6 +238,10 @@
@media (max-width: $screen-xs-min) {
margin-left: 0;
}
li.active {
font-weight: bold;
}
}
}
......@@ -246,6 +250,11 @@
height: 51px;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
&::-webkit-scrollbar {
display: none;
}
li {
......@@ -279,4 +288,8 @@
margin-top: 96px;
}
}
.right-sidebar {
top: ($header-height * 2) + 2;
}
}
......@@ -119,8 +119,8 @@ $border-white-light: #f1f2f4;
$border-white-normal: #d6dae2;
$border-white-dark: #c6cacf;
$border-gray-light: rgba(0, 0, 0, 0.06);
$border-gray-normal: rgba(0, 0, 0, 0.10);;
$border-gray-light: #dcdcdc;
$border-gray-normal: rgba(0, 0, 0, 0.10);
$border-gray-dark: #c6cacf;
$border-green-light: #2faa60;
......
......@@ -26,8 +26,13 @@
}
.project-home-panel {
padding-bottom: 40px;
border-bottom: 1px solid $border-color;
background: $white-light;
text-align: left;
padding: 24px 0;
.container-fluid {
position: relative;
}
.cover-controls {
.project-settings-dropdown {
......@@ -43,21 +48,55 @@
}
}
.project-identicon-holder {
margin-bottom: 16px;
.cover-title {
margin-bottom: 0;
}
.project-image-container {
@include make-sm-column(1);
max-width: 86px;
min-width: 86px;
padding-right: 0;
margin: 11px 0;
.avatar, .identicon {
margin: 0 auto;
float: none;
@media (max-width: $screen-md-max) {
padding-left: 0;
margin: 0 0 10px;
max-width: none;
min-width: none;
.avatar.s70 {
margin: auto;
}
}
}
.identicon {
@include border-radius(50%);
.project-info {
@include make-sm-column(10);
h1 {
font-size: 24px;
font-weight: normal;
margin: 0;
}
.project-home-desc {
p {
margin: 0;
}
}
}
.identicon {
float: left;
@include border-radius(50%);
}
.avatar {
float: none;
}
.notifications-btn {
margin-top: -28px;
.fa-bell {
margin-right: 6px;
......@@ -69,28 +108,45 @@
}
.project-repo-buttons {
margin-top: 20px;
margin-bottom: 0;
font-size: 0;
.count-buttons {
display: block;
margin-bottom: 20px;
}
.btn {
@include btn-gray;
padding: 3px 10px;
text-transform: none;
background-color: $background-color;
.clone-row {
.split-repo-buttons,
.project-clone-holder {
display: inline-block;
.fa {
color: $layout-link-gray;
}
.split-repo-buttons {
margin: 0 12px;
.fa-caret-down {
margin-left: 3px;
}
}
.btn {
@include btn-gray;
text-transform: none;
.btn-group:not(:first-child):not(:last-child) > .btn {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
form {
margin-left: 10px;
}
.count-buttons {
display: inline-block;
vertical-align: top;
margin-top: 16px;
}
.project-clone-holder {
display: inline-block;
margin-top: 16px;
input {
height: 29px;
}
}
.count-with-arrow {
......@@ -140,14 +196,14 @@
line-height: 13px;
padding: $gl-vert-padding $gl-padding;
letter-spacing: .4px;
padding: 10px 14px;
padding: 7px 14px;
text-align: center;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
background-image: none;
white-space: nowrap;
margin: 0 11px 0 4px;
margin: 0 10px 0 4px;
a {
color: inherit;
......@@ -159,6 +215,30 @@
}
}
}
.project-right-buttons {
position: absolute;
right: 16px;
bottom: 0;
.btn {
padding: 3px 10px;
background-color: $background-color;
}
@media (max-width: 1304px) {
top: 0;
}
}
@media (max-width: $screen-md-max) {
text-align: center;
.project-info,
.project-image-container {
width: 100%;
}
}
}
.split-one {
......@@ -289,11 +369,11 @@ a.deploy-project-label {
}
.project-stats {
text-align: center;
margin-top: $gl-padding;
margin-bottom: 0;
padding-top: 10px;
padding-bottom: 4px;
padding: 16px 0;
background-color: $white-light;
font-size: 0;
ul.nav {
display: inline-block;
......@@ -304,12 +384,11 @@ a.deploy-project-label {
}
.nav > li > a {
@include btn-default;
@include btn-gray;
background-color: transparent;
border: 1px solid #f7f8fa;
margin-left: 12px;
margin-right: 12px;
padding: 0 10px;
font-size: 15px;
color: $notes-light-color;
}
li {
......@@ -329,6 +408,10 @@ a.deploy-project-label {
background-color: #f0f2f5;
}
}
&.row-content-block.second-block {
margin-top: 0;
}
}
pre.light-well {
......@@ -446,9 +529,14 @@ pre.light-well {
border-top: 0;
.edit-project-readme {
z-index: 100;
z-index: 2;
position: relative;
}
.wiki h1 {
border-bottom: none;
padding: 0;
}
}
.git-clone-holder {
......
......@@ -95,7 +95,9 @@ module TabHelper
end
def project_tab_class
return "active" if current_page?(controller: "/projects", action: :edit, id: @project)
if controller.controller_path.start_with?('projects')
return 'active'
end
if ['services', 'hooks', 'deploy_keys', 'protected_branches'].include? controller.controller_name
"active"
......
%ul.nav.nav-sidebar
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: 'home'}) do
= link_to dashboard_projects_path, title: 'Projects' do
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: {class: "#{project_tab_class} home"}) do
= link_to dashboard_projects_path, title: 'Projects', class: 'dashboard-shortcuts-projects' do
= icon('bookmark fw')
%span
Projects
......@@ -11,7 +11,7 @@
Todos
%span.count.todos-pending-count= number_with_delimiter(todos_pending_count)
= nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do
= link_to activity_dashboard_path, class: 'dashboard-shortcuts-activity', title: 'Activity' do
= icon('dashboard fw')
%span
Activity
......@@ -26,13 +26,13 @@
%span
Milestones
= nav_link(path: 'dashboard#issues') do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'shortcuts-issues' do
= link_to assigned_issues_dashboard_path, title: 'Issues', class: 'dashboard-shortcuts-issues' do
= icon('exclamation-circle fw')
%span
Issues
%span.count= number_with_delimiter(current_user.assigned_issues.opened.count)
= nav_link(path: 'dashboard#merge_requests') do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'dashboard-shortcuts-merge_requests' do
= icon('tasks fw')
%span
Merge Requests
......
%ul.nav.nav-sidebar
- if @project.group
= nav_link do
= link_to group_path(@project.group), title: 'Go to group', class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Go to group
- else
= nav_link do
= link_to root_path, title: 'Go to dashboard', class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Go to dashboard
%li.separate-item
- if current_user
.controls
- access = user_max_access_in_project(current_user.id, @project)
- can_edit = can?(current_user, :admin_project, @project)
.dropdown.project-settings-dropdown
%a.dropdown-new.btn.btn-default#project-settings-button{href: '#', 'data-toggle' => 'dropdown'}
= icon('cog')
= icon('caret-down')
%ul.dropdown-menu.dropdown-menu-align-right
= render 'layouts/nav/project_settings'
%li.divider
- if can_edit
%li
= link_to edit_project_path(@project) do
Edit Project
- if access
%li
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
Leave Project
%ul.nav-links
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
= icon('bookmark fw')
......@@ -44,7 +50,7 @@
= icon('ship fw')
%span
Pipelines
%span.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count)
%span.badge.count.ci_counter= number_with_delimiter(@project.ci_commits.running_or_pending.count)
- if project_nav_tab? :builds
= nav_link(controller: %w(builds)) do
......@@ -52,7 +58,7 @@
= icon('cubes fw')
%span
Builds
%span.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all))
%span.badge.count.builds_counter= number_with_delimiter(@project.builds.running_or_pending.count(:all))
- if project_nav_tab? :container_registry
= nav_link(controller: %w(container_registry)) do
......@@ -82,7 +88,7 @@
%span
Issues
- if @project.default_issues_tracker?
%span.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count)
%span.badge.count.issue_counter= number_with_delimiter(@project.issues.visible_to_user(current_user).opened.count)
- if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do
......@@ -90,14 +96,7 @@
= icon('tasks fw')
%span
Merge Requests
%span.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
- if project_nav_tab? :team
= nav_link(controller: [:project_members, :teams]) do
= link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do
= icon('users fw')
%span
Members
%span.badge.count.merge_counter= number_with_delimiter(@project.merge_requests.opened.count)
- if project_nav_tab? :labels
= nav_link(controller: :labels) do
......@@ -113,13 +112,6 @@
%span
Wiki
- if project_nav_tab? :forks
= nav_link(controller: :forks, action: :index) do
= link_to namespace_project_forks_path(@project.namespace, @project), title: 'Forks' do
= icon('code-fork fw')
%span
Forks
- if project_nav_tab? :snippets
= nav_link(controller: :snippets) do
= link_to namespace_project_snippets_path(@project.namespace, @project), title: 'Snippets', class: 'shortcuts-snippets' do
......@@ -127,13 +119,6 @@
%span
Snippets
- if project_nav_tab? :settings
= nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do
= link_to edit_project_path(@project), title: 'Settings' do
= icon('cogs fw')
%span
Settings
-# Global shortcut to network page for compatibility
- if project_nav_tab? :network
%li.hidden
......
%ul.nav.nav-sidebar
= nav_link do
= link_to project_path(@project), title: 'Go to project', class: 'back-link' do
= icon('caret-square-o-left fw')
- if project_nav_tab? :team
= nav_link(controller: [:project_members, :teams]) do
= link_to namespace_project_project_members_path(@project.namespace, @project), title: 'Members', class: 'team-tab tab' do
%span
Go to project
Members
%li.separate-item
%ul.sidebar-subnav
= nav_link(path: 'projects#edit') do
= link_to edit_project_path(@project), title: 'Project Settings' do
= icon('pencil-square-o fw')
%span
Project Settings
- if @project.allowed_to_share_with_group?
= nav_link(controller: :group_links) do
= link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do
= icon('share-square-o fw')
%span
Groups
= nav_link(controller: :deploy_keys) do
= link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
= icon('key fw')
%span
Deploy Keys
= nav_link(controller: :hooks) do
= link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do
= icon('link fw')
%span
Webhooks
= nav_link(controller: :services) do
= link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
= icon('cogs fw')
%span
Services
= nav_link(controller: :protected_branches) do
= link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
= icon('lock fw')
%span
Protected Branches
- if @project.allowed_to_share_with_group?
= nav_link(controller: :group_links) do
= link_to namespace_project_group_links_path(@project.namespace, @project), title: "Groups" do
%span
Groups
= nav_link(controller: :deploy_keys) do
= link_to namespace_project_deploy_keys_path(@project.namespace, @project), title: 'Deploy Keys' do
%span
Deploy Keys
= nav_link(controller: :hooks) do
= link_to namespace_project_hooks_path(@project.namespace, @project), title: 'Webhooks' do
%span
Webhooks
= nav_link(controller: :services) do
= link_to namespace_project_services_path(@project.namespace, @project), title: 'Services' do
%span
Services
= nav_link(controller: :protected_branches) do
= link_to namespace_project_protected_branches_path(@project.namespace, @project), title: 'Protected Branches' do
%span
Protected Branches
- if @project.builds_enabled?
= nav_link(controller: :runners) do
= link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do
= icon('cog fw')
%span
Runners
= nav_link(controller: :variables) do
= link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do
= icon('code fw')
%span
Variables
= nav_link(controller: :triggers) do
= link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
= icon('retweet fw')
%span
Triggers
= nav_link(controller: :badges) do
= link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
= icon('star-half-empty fw')
%span
Badges
- if @project.builds_enabled?
= nav_link(controller: :runners) do
= link_to namespace_project_runners_path(@project.namespace, @project), title: 'Runners' do
%span
Runners
= nav_link(controller: :variables) do
= link_to namespace_project_variables_path(@project.namespace, @project), title: 'Variables' do
%span
Variables
= nav_link(controller: :triggers) do
= link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
%span
Triggers
= nav_link(controller: :badges) do
= link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
%span
Badges
- page_title @project.name_with_namespace
- page_description @project.description unless page_description
- header_title project_title(@project) unless header_title
- sidebar "project" unless sidebar
- nav "project"
- content_for :scripts_body_top do
- project = @target_project || @project
......
- page_title "Settings"
- header_title project_title(@project, "Settings", edit_project_path(@project))
- sidebar "project_settings"
- nav "project"
= render template: "layouts/project"
- empty_repo = @project.empty_repo?
.project-home-panel.cover-block.clearfix{:class => ("empty-project" if empty_repo)}
.project-identicon-holder
= project_icon(@project, alt: '', class: 'project-avatar avatar s90')
.cover-title.project-home-desc
%h1
= @project.name
%span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)}
= visibility_level_icon(@project.visibility_level, fw: false)
- if @project.description.present?
.cover-desc.project-home-desc
= markdown(@project.description, pipeline: :description)
- if forked_from_project = @project.forked_from_project
.cover-desc
Forked from
= link_to project_path(forked_from_project) do
= forked_from_project.namespace.try(:name)
.cover-controls
- if current_user
= link_to namespace_project_path(@project.namespace, @project, format: :atom, private_token: current_user.private_token), class: 'btn btn-gray' do
= icon('rss')
- access = user_max_access_in_project(current_user.id, @project)
- can_edit = can?(current_user, :admin_project, @project)
- if access || can_edit
%span.dropdown.project-settings-dropdown
%a.dropdown-new.btn.btn-gray#project-settings-button{href: '#', 'data-toggle' => 'dropdown'}
= icon('cog')
= icon('angle-down')
%ul.dropdown-menu.dropdown-menu-right
- if can_edit
%li
= link_to edit_project_path(@project) do
Edit Project
- if access
%li
= link_to leave_namespace_project_project_members_path(@project.namespace, @project),
data: { confirm: leave_project_message(@project) }, method: :delete, title: 'Leave project' do
Leave Project
.project-repo-buttons
.split-one.count-buttons
= render 'projects/buttons/star'
= render 'projects/buttons/fork'
.clone-row
.project-clone-holder
= render "shared/clone_panel"
.split-repo-buttons
.btn-group.pull-left
= render "projects/buttons/download"
= render 'projects/buttons/dropdown'
.container-fluid.container-limited
.row
.project-image-container
= project_icon(@project, alt: '', class: 'project-avatar avatar s70')
.project-info
.cover-title.project-home-desc
%h1
= @project.name
%span.visibility-icon.has-tooltip{data: { container: 'body' }, title: visibility_icon_description(@project)}
= visibility_level_icon(@project.visibility_level, fw: false)
- if @project.description.present?
.cover-desc.project-home-desc
= markdown(@project.description, pipeline: :description)
- if forked_from_project = @project.forked_from_project
.cover-desc
Forked from
= link_to project_path(forked_from_project) do
= forked_from_project.namespace.try(:name)
.project-repo-buttons
.count-buttons
= render 'projects/buttons/star'
= render 'projects/buttons/fork'
.project-clone-holder
= render "shared/clone_panel"
.project-repo-buttons.btn-group.project-right-buttons
= render "projects/buttons/download"
= render 'projects/buttons/dropdown'
= render 'projects/buttons/notifications'
:javascript
......
......@@ -2,7 +2,7 @@
.btn-group
%a.btn.dropdown-toggle{href: '#', "data-toggle" => "dropdown"}
= icon('plus')
%ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
%ul.dropdown-menu.dropdown-menu-align-right.project-home-dropdown
- can_create_issue = can?(current_user, :create_issue, @project)
- merge_project = can?(current_user, :create_merge_request, @project) ? @project : (current_user && current_user.fork_of(@project))
- can_create_snippet = can?(current_user, :create_snippet, @project)
......
- if @notification_setting
= form_for @notification_setting, url: namespace_project_notification_setting_path(@project.namespace.becomes(Namespace), @project), method: :patch, remote: true, html: { class: 'inline', id: 'notification-form' } do |f|
= f.hidden_field :level
%span.dropdown
.dropdown
%a.dropdown-new.btn.notifications-btn#notifications-button{href: '#', "data-toggle" => "dropdown"}
= icon('bell')
= notification_title(@notification_setting.level)
= icon('angle-down')
%ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
= icon('caret-down')
%ul.dropdown-menu.dropdown-menu-align-right.project-home-dropdown
- NotificationSetting.levels.each do |level|
= notification_list_item(level.first, @notification_setting)
......@@ -13,50 +13,50 @@
= render "home_panel"
.project-stats.row-content-block.second-block
%ul.nav
%li
= link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
= pluralize(number_with_delimiter(@project.commit_count), 'commit')
%li
= link_to namespace_project_branches_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.branch_names.count), 'branch')
%li
= link_to namespace_project_tags_path(@project.namespace, @project) do
= pluralize(number_with_delimiter(@repository.tag_names.count), 'tag')
%li
= link_to project_files_path(@project) do
= repository_size
- if default_project_view != 'readme' && @repository.readme
.container-fluid.container-limited
%ul.nav
%li
= link_to 'Readme', readme_path(@project)
- if @repository.changelog
= link_to project_files_path(@project) do
Files (#{repository_size})
%li
= link_to 'Changelog', changelog_path(@project)
- if @repository.license_blob
= link_to namespace_project_commits_path(@project.namespace, @project, current_ref) do
#{'Commit'.pluralize(@project.commit_count)} (#{number_with_delimiter(@project.commit_count)})
%li
= link_to license_short_name(@project), license_path(@project)
- if @repository.contribution_guide
= link_to namespace_project_branches_path(@project.namespace, @project) do
#{'Branch'.pluralize(@repository.branch_names.count)} (#{number_with_delimiter(@repository.branch_names.count)})
%li
= link_to 'Contribution guide', contribution_guide_path(@project)
= link_to namespace_project_tags_path(@project.namespace, @project) do
#{'Tag'.pluralize(@repository.tag_names.count)} (#{number_with_delimiter(@repository.tag_names.count)})
- if default_project_view != 'readme' && @repository.readme
%li
= link_to 'Readme', readme_path(@project)
- if @repository.changelog
%li
= link_to 'Changelog', changelog_path(@project)
- if @repository.license_blob
%li
= link_to license_short_name(@project), license_path(@project)
- if @repository.contribution_guide
%li
= link_to 'Contribution guide', contribution_guide_path(@project)
- if current_user && can_push_branch?(@project, @project.default_branch)
- unless @repository.changelog
%li.missing
= link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
Add Changelog
- unless @repository.license_blob
%li.missing
= link_to add_special_file_path(@project, file_name: 'LICENSE') do
Add License
- unless @repository.contribution_guide
%li.missing
= link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
Add Contribution guide
- if current_user && can_push_branch?(@project, @project.default_branch)
- unless @repository.changelog
%li.missing
= link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
Add Changelog
- unless @repository.license_blob
%li.missing
= link_to add_special_file_path(@project, file_name: 'LICENSE') do
Add License
- unless @repository.contribution_guide
%li.missing
= link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
Add Contribution guide
- if @repository.commit
.content-block.second-block.white
......
......@@ -5,7 +5,7 @@
%a#clone-dropdown.clone-dropdown-btn.btn{href: '#', 'data-toggle' => 'dropdown'}
%span
= default_clone_protocol.upcase
= icon('angle-down')
= icon('caret-down')
%ul.dropdown-menu.dropdown-menu-right.clone-options-dropdown
%li
= ssh_clone_button(project)
......
......@@ -30,11 +30,6 @@ Feature: Project Active Tab
Then the active main tab should be Merge Requests
And no other main tabs should be active
Scenario: On Project Members
Given I visit my project's members page
Then the active main tab should be Members
And no other main tabs should be active
Scenario: On Project Wiki
Given I visit my project's wiki page
Then the active main tab should be Wiki
......@@ -49,13 +44,6 @@ Feature: Project Active Tab
# Sub Tabs: Settings
Scenario: On Project Settings/Edit
Given I visit my project's settings page
And I click the "Edit" tab
Then the active sub nav should be Edit
And no other sub navs should be active
And the active main tab should be Settings
Scenario: On Project Settings/Hooks
Given I visit my project's settings page
And I click the "Hooks" tab
......@@ -70,6 +58,12 @@ Feature: Project Active Tab
And no other sub navs should be active
And the active main tab should be Settings
Scenario: On Project Members
Given I visit my project's members page
Then the active sub nav should be Members
And no other sub navs should be active
And the active main tab should be Settings
# Sub Tabs: Commits
Scenario: On Project Commits/Commits
......
......@@ -18,15 +18,6 @@ Feature: Project
Then I should see the default project avatar
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
And I visit project "Shop" page
Then I should see project "Shop" README
......
class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedActiveTab
include SharedSidebarActiveTab
step 'the active main tab should be Home' do
ensure_active_main_tab('Overview')
......@@ -34,4 +34,12 @@ class Spinach::Features::AdminActiveTab < Spinach::FeatureSteps
step 'the active main tab should be Messages' do
ensure_active_main_tab('Messages')
end
step 'no other main tabs should be active' do
expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
end
def ensure_active_main_tab(content)
expect(find('.nav-sidebar > li.active')).to have_content(content)
end
end
class Spinach::Features::DashboardActiveTab < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedActiveTab
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
end
include SharedSidebarActiveTab
end
......@@ -2,5 +2,6 @@ class Spinach::Features::DashboardShortcuts < Spinach::FeatureSteps
include SharedAuthentication
include SharedPaths
include SharedProject
include SharedActiveTab
include SharedSidebarActiveTab
include SharedShortcuts
end
......@@ -22,8 +22,4 @@ class Spinach::Features::ProfileActiveTab < Spinach::FeatureSteps
step 'the active main tab should be Audit Log' do
ensure_active_main_tab('Audit Log')
end
def ensure_active_main_tab(content)
expect(find('.layout-nav li.active')).to have_content(content)
end
end
......@@ -16,12 +16,14 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
end
step 'I click the "Snippets" tab' do
click_link('Snippets')
page.within('.layout-nav') do
click_link('Snippets')
end
end
step 'I click the "Edit" tab' do
page.within '.sidebar-subnav' do
click_link('Project Settings')
step 'I click the "Edit Project"' do
page.within '.layout-nav .controls' do
click_link('Edit Project')
end
end
......@@ -33,14 +35,10 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
click_link('Deploy Keys')
end
step 'the active sub nav should be Team' do
step 'the active sub nav should be Members' do
ensure_active_sub_nav('Members')
end
step 'the active sub nav should be Edit' do
ensure_active_sub_nav('Project')
end
step 'the active sub nav should be Hooks' do
ensure_active_sub_nav('Webhooks')
end
......@@ -56,7 +54,9 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
end
step 'I click the "Branches" tab' do
click_link('Branches')
page.within '.content' do
click_link('Branches')
end
end
step 'I click the "Tags" tab' do
......@@ -82,11 +82,15 @@ class Spinach::Features::ProjectActiveTab < Spinach::FeatureSteps
# Sub Tabs: Issues
step 'I click the "Milestones" tab' do
click_link('Milestones')
page.within('.layout-nav') do
click_link('Milestones')
end
end
step 'I click the "Labels" tab' do
click_link('Labels')
page.within('.layout-nav') do
click_link('Labels')
end
end
step 'the active sub tab should be Issues' do
......
......@@ -36,7 +36,7 @@ class Spinach::Features::ProjectFork < Spinach::FeatureSteps
end
step 'I goto the Merge Requests page' do
page.within '.page-sidebar-expanded' do
page.within '.layout-nav' do
click_link "Merge Requests"
end
end
......
......@@ -114,7 +114,9 @@ class Spinach::Features::Project < Spinach::FeatureSteps
end
step 'I should not see "Snippets" button' do
expect(page).not_to have_link 'Snippets'
page.within '.content' do
expect(page).not_to have_link 'Snippets'
end
end
step 'project "Shop" belongs to group' do
......@@ -123,14 +125,6 @@ class Spinach::Features::Project < Spinach::FeatureSteps
@project.save!
end
step 'I should see back to dashboard button' do
expect(page).to have_content 'Go to dashboard'
end
step 'I should see back to group button' do
expect(page).to have_content 'Go to group'
end
step 'I click notifications drop down button' do
click_link 'notifications-button'
end
......
......@@ -52,7 +52,7 @@ class Spinach::Features::ProjectMilestone < Spinach::FeatureSteps
end
step 'I click link "Labels"' do
page.within('.nav-links') do
page.within('.layout-nav .nav-links') do
page.find(:xpath, "//a[@href='#tab-labels']").click
end
end
......
......@@ -3,6 +3,7 @@ class Spinach::Features::ProjectShortcuts < Spinach::FeatureSteps
include SharedPaths
include SharedProject
include SharedProjectTab
include SharedShortcuts
step 'I press "g" and "f"' do
find('body').native.send_key('g')
......
......@@ -337,13 +337,15 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end
step 'I should see buttons for allowed commands' do
expect(page).to have_content 'Raw'
expect(page).to have_content 'History'
expect(page).to have_content 'Permalink'
expect(page).not_to have_content 'Edit'
expect(page).not_to have_content 'Blame'
expect(page).to have_content 'Delete'
expect(page).to have_content 'Replace'
page.within '.content' do
expect(page).to have_content 'Raw'
expect(page).to have_content 'History'
expect(page).to have_content 'Permalink'
expect(page).not_to have_content 'Edit'
expect(page).not_to have_content 'Blame'
expect(page).to have_content 'Delete'
expect(page).to have_content 'Replace'
end
end
step 'I should see a notice about a new fork having been created' do
......
......@@ -2,7 +2,7 @@ module SharedActiveTab
include Spinach::DSL
def ensure_active_main_tab(content)
expect(find('.nav-sidebar > li.active')).to have_content(content)
expect(find('.layout-nav li.active')).to have_content(content)
end
def ensure_active_sub_tab(content)
......@@ -10,11 +10,11 @@ module SharedActiveTab
end
def ensure_active_sub_nav(content)
expect(find('.sidebar-subnav > li.active')).to have_content(content)
expect(find('.layout-nav .controls li.active')).to have_content(content)
end
step 'no other main tabs should be active' do
expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 1)
end
step 'no other sub tabs should be active' do
......@@ -22,26 +22,6 @@ module SharedActiveTab
end
step 'no other sub navs should be active' do
expect(page).to have_selector('.sidebar-subnav > li.active', count: 1)
end
step 'the active main tab should be Home' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Projects' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Issues' do
ensure_active_main_tab('Issues')
end
step 'the active main tab should be Merge Requests' do
ensure_active_main_tab('Merge Requests')
end
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
expect(page).to have_selector('.layout-nav .controls li.active', count: 1)
end
end
......@@ -111,7 +111,7 @@ module SharedIssuable
step 'I sort the list by "Oldest updated"' do
find('button.dropdown-toggle.btn').click
page.within('ul.dropdown-menu.dropdown-menu-align-right li') do
page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
click_link "Oldest updated"
end
end
......@@ -119,7 +119,7 @@ module SharedIssuable
step 'I sort the list by "Least popular"' do
find('button.dropdown-toggle.btn').click
page.within('ul.dropdown-menu.dropdown-menu-align-right li') do
page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
click_link 'Least popular'
end
end
......@@ -127,13 +127,13 @@ module SharedIssuable
step 'I sort the list by "Most popular"' do
find('button.dropdown-toggle.btn').click
page.within('ul.dropdown-menu.dropdown-menu-align-right li') do
page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
click_link 'Most popular'
end
end
step 'The list should be sorted by "Oldest updated"' do
page.within('div.dropdown.inline.prepend-left-10') do
page.within('.content div.dropdown.inline.prepend-left-10') do
expect(page.find('button.dropdown-toggle.btn')).to have_content('Oldest updated')
end
end
......
......@@ -41,9 +41,7 @@ module SharedProjectTab
end
step 'the active main tab should be Settings' do
page.within '.nav-sidebar' do
expect(page).to have_content('Go to project')
end
expect(page).to have_selector('.layout-nav .nav-links > li.active', count: 0)
end
step 'the active main tab should be Activity' do
......
module SharedActiveTab
module SharedShortcuts
include Spinach::DSL
step 'I press "g" and "p"' do
......
module SharedSidebarActiveTab
include Spinach::DSL
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
end
step 'no other main tabs should be active' do
expect(page).to have_selector('.nav-sidebar > li.active', count: 1)
end
def ensure_active_main_tab(content)
expect(find('.nav-sidebar li.active')).to have_content(content)
end
step 'the active main tab should be Home' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Projects' do
ensure_active_main_tab('Projects')
end
step 'the active main tab should be Issues' do
ensure_active_main_tab('Issues')
end
step 'the active main tab should be Merge Requests' do
ensure_active_main_tab('Merge Requests')
end
step 'the active main tab should be Help' do
ensure_active_main_tab('Help')
end
end
......@@ -8,12 +8,10 @@ feature 'list of badges' do
project = create(:project)
project.team << [user, :master]
login_as(user)
visit edit_namespace_project_path(project.namespace, project)
visit namespace_project_badges_path(project.namespace, project)
end
scenario 'user displays list of badges' do
click_link 'Badges'
expect(page).to have_content 'build status'
expect(page).to have_content 'Markdown'
expect(page).to have_content 'HTML'
......@@ -26,7 +24,6 @@ feature 'list of badges' do
end
scenario 'user changes current ref on badges list page', js: true do
click_link 'Badges'
select2('improve/awesome', from: '#ref')
expect(page).to have_content 'badges/improve/awesome/build.svg'
......
......@@ -12,7 +12,7 @@ feature 'Master updates tag', feature: true do
context 'from the tags list page' do
scenario 'updates the release notes' do
page.within(first('.controls')) do
page.within(first('.content-list .controls')) do
click_link 'Edit release notes'
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