Commit 97df9e86 authored by Dennis Tang's avatar Dennis Tang Committed by Mike Greiling

Port "Further improvements to Project overview UI" to EE

parent b6052c49
...@@ -12,6 +12,10 @@ export default function notificationsDropdown() { ...@@ -12,6 +12,10 @@ export default function notificationsDropdown() {
const form = $(this).parents('.notification-form:first'); const form = $(this).parents('.notification-form:first');
form.find('.js-notification-loading').toggleClass('fa-bell fa-spin fa-spinner'); form.find('.js-notification-loading').toggleClass('fa-bell fa-spin fa-spinner');
if (form.hasClass('no-label')) {
form.find('.js-notification-loading').toggleClass('hidden');
form.find('.js-notifications-icon').toggleClass('hidden');
}
form.find('#notification_setting_level').val(notificationLevel); form.find('#notification_setting_level').val(notificationLevel);
form.submit(); form.submit();
}); });
......
...@@ -13,6 +13,9 @@ export default class Project { ...@@ -13,6 +13,9 @@ export default class Project {
const $cloneOptions = $('ul.clone-options-dropdown'); const $cloneOptions = $('ul.clone-options-dropdown');
const $projectCloneField = $('#project_clone'); const $projectCloneField = $('#project_clone');
const $cloneBtnLabel = $('.js-git-clone-holder .js-clone-dropdown-label'); const $cloneBtnLabel = $('.js-git-clone-holder .js-clone-dropdown-label');
const mobileCloneField = document.querySelector(
'.js-mobile-git-clone .js-clone-dropdown-label',
);
const selectedCloneOption = $cloneBtnLabel.text().trim(); const selectedCloneOption = $cloneBtnLabel.text().trim();
if (selectedCloneOption.length > 0) { if (selectedCloneOption.length > 0) {
...@@ -41,7 +44,11 @@ export default class Project { ...@@ -41,7 +44,11 @@ export default class Project {
cloneUrlPrimary: $this.data('primaryUrl') || '', cloneUrlPrimary: $this.data('primaryUrl') || '',
}); });
if (mobileCloneField) {
mobileCloneField.dataset.clipboardText = url;
} else {
$projectCloneField.val(url); $projectCloneField.val(url);
}
$('.js-git-empty .js-clone').text(url); $('.js-git-empty .js-clone').text(url);
}); });
// Ref switcher // Ref switcher
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
&.s46 { @include avatar-size(46px, 15px); } &.s46 { @include avatar-size(46px, 15px); }
&.s48 { @include avatar-size(48px, 10px); } &.s48 { @include avatar-size(48px, 10px); }
&.s60 { @include avatar-size(60px, 12px); } &.s60 { @include avatar-size(60px, 12px); }
&.s64 { @include avatar-size(64px, 14px); }
&.s70 { @include avatar-size(70px, 14px); } &.s70 { @include avatar-size(70px, 14px); }
&.s90 { @include avatar-size(90px, 15px); } &.s90 { @include avatar-size(90px, 15px); }
&.s100 { @include avatar-size(100px, 15px); } &.s100 { @include avatar-size(100px, 15px); }
...@@ -84,6 +85,7 @@ ...@@ -84,6 +85,7 @@
&.s40 { font-size: 16px; line-height: 38px; } &.s40 { font-size: 16px; line-height: 38px; }
&.s48 { font-size: 20px; line-height: 46px; } &.s48 { font-size: 20px; line-height: 46px; }
&.s60 { font-size: 32px; line-height: 58px; } &.s60 { font-size: 32px; line-height: 58px; }
&.s64 { font-size: 32px; line-height: 64px; }
&.s70 { font-size: 34px; line-height: 70px; } &.s70 { font-size: 34px; line-height: 70px; }
&.s90 { font-size: 36px; line-height: 88px; } &.s90 { font-size: 36px; line-height: 88px; }
&.s100 { font-size: 36px; line-height: 98px; } &.s100 { font-size: 36px; line-height: 98px; }
......
...@@ -142,8 +142,14 @@ ...@@ -142,8 +142,14 @@
&.btn-sm { &.btn-sm {
padding: 4px 10px; padding: 4px 10px;
font-size: 13px; font-size: $gl-btn-small-font-size;
line-height: 18px; line-height: $gl-btn-small-line-height;
}
&.btn-xs {
padding: 2px $gl-btn-padding;
font-size: $gl-btn-small-font-size;
line-height: $gl-btn-small-line-height;
} }
&.btn-success, &.btn-success,
......
...@@ -39,15 +39,6 @@ ...@@ -39,15 +39,6 @@
.git-clone-holder { .git-clone-holder {
display: none; display: none;
} }
// Display Star and Fork buttons without counters on mobile.
.project-repo-buttons {
display: block;
.count-buttons .count-badge {
margin-top: $gl-padding-8;
}
}
} }
.group-buttons { .group-buttons {
......
...@@ -198,6 +198,7 @@ $well-light-text-color: #5b6169; ...@@ -198,6 +198,7 @@ $well-light-text-color: #5b6169;
$gl-font-size: 14px; $gl-font-size: 14px;
$gl-font-size-xs: 11px; $gl-font-size-xs: 11px;
$gl-font-size-small: 12px; $gl-font-size-small: 12px;
$gl-font-size-large: 16px;
$gl-font-weight-normal: 400; $gl-font-weight-normal: 400;
$gl-font-weight-bold: 600; $gl-font-weight-bold: 600;
$gl-text-color: #2e2e2e; $gl-text-color: #2e2e2e;
...@@ -271,7 +272,8 @@ $performance-bar-height: 35px; ...@@ -271,7 +272,8 @@ $performance-bar-height: 35px;
$flash-height: 52px; $flash-height: 52px;
$context-header-height: 60px; $context-header-height: 60px;
$breadcrumb-min-height: 48px; $breadcrumb-min-height: 48px;
$project-title-row-height: 24px; $project-title-row-height: 64px;
$project-avatar-mobile-size: 24px;
$gl-line-height: 16px; $gl-line-height: 16px;
$gl-line-height-24: 24px; $gl-line-height-24: 24px;
...@@ -373,6 +375,8 @@ $gl-btn-padding: 10px; ...@@ -373,6 +375,8 @@ $gl-btn-padding: 10px;
$gl-btn-line-height: 16px; $gl-btn-line-height: 16px;
$gl-btn-vert-padding: 8px; $gl-btn-vert-padding: 8px;
$gl-btn-horz-padding: 12px; $gl-btn-horz-padding: 12px;
$gl-btn-small-font-size: 13px;
$gl-btn-small-line-height: 13px;
/* /*
* Badges * Badges
......
...@@ -144,7 +144,6 @@ ...@@ -144,7 +144,6 @@
.group-home-panel { .group-home-panel {
padding-top: 24px; padding-top: 24px;
padding-bottom: 24px; padding-bottom: 24px;
border-bottom: 1px solid $border-color;
.group-avatar { .group-avatar {
float: none; float: none;
...@@ -155,7 +154,6 @@ ...@@ -155,7 +154,6 @@
} }
} }
.project-title,
.group-title { .group-title {
margin-top: 10px; margin-top: 10px;
margin-bottom: 10px; margin-bottom: 10px;
...@@ -195,44 +193,78 @@ ...@@ -195,44 +193,78 @@
} }
.project-home-panel { .project-home-panel {
padding-top: $gl-padding-8; padding-top: $gl-padding;
padding-bottom: $gl-padding-24; padding-bottom: $gl-padding;
.project-title-row {
margin-right: $gl-padding-8;
}
.project-avatar { .project-avatar {
width: $project-title-row-height; width: $project-title-row-height;
height: $project-title-row-height; height: $project-title-row-height;
flex-shrink: 0; flex-shrink: 0;
flex-basis: $project-title-row-height; flex-basis: $project-title-row-height;
margin: 0 $gl-padding-8 0 0; margin: 0 $gl-padding 0 0;
} }
.project-title { .project-title {
margin-top: 8px;
margin-bottom: 5px;
font-size: 20px; font-size: 20px;
line-height: $project-title-row-height; line-height: $gl-line-height-24;
font-weight: bold; font-weight: bold;
.icon {
font-size: $gl-font-size-large;
} }
.project-metadata { .project-visibility {
font-weight: normal;
font-size: 14px;
line-height: $gl-btn-line-height;
color: $gl-text-color-secondary; color: $gl-text-color-secondary;
}
.project-tag-list {
font-size: $gl-font-size;
font-weight: $gl-font-weight-normal;
.icon { .icon {
position: relative;
top: 3px;
margin-right: $gl-padding-4; margin-right: $gl-padding-4;
font-size: 16px; }
}
} }
.project-visibility, .project-title-row {
.project-license, @include media-breakpoint-down(sm) {
.project-tag-list { .project-avatar {
margin-right: $gl-padding-8; width: $project-avatar-mobile-size;
height: $project-avatar-mobile-size;
flex-basis: $project-avatar-mobile-size;
.avatar {
font-size: 20px;
line-height: 46px;
}
}
.project-title {
margin-top: 4px;
margin-bottom: 2px;
font-size: $gl-font-size;
line-height: $gl-font-size-large;
} }
.project-tag-list,
.project-metadata {
font-size: $gl-font-size-small;
}
}
}
.project-metadata {
font-weight: normal;
font-size: 14px;
line-height: $gl-btn-line-height;
color: $gl-text-color-secondary;
.project-license { .project-license {
.btn { .btn {
line-height: 0; line-height: 0;
...@@ -240,13 +272,23 @@ ...@@ -240,13 +272,23 @@
} }
} }
.project-tag-list, .access-request-link,
.project-license { .project-tag-list {
.icon { padding-left: $gl-padding-8;
position: relative; border-left: 1px solid $gl-text-color-secondary;
top: 2px;
} }
} }
.project-description {
@include media-breakpoint-up(md) {
font-size: $gl-font-size-large;
}
}
.notifications-btn {
.fa-bell {
margin-right: 0;
}
} }
} }
...@@ -298,14 +340,6 @@ ...@@ -298,14 +340,6 @@
vertical-align: top; vertical-align: top;
margin-top: $gl-padding; margin-top: $gl-padding;
.count-badge {
height: $input-height;
.icon {
top: -1px;
}
}
.count-badge-count, .count-badge-count,
.count-badge-button { .count-badge-button {
border: 1px solid $border-color; border: 1px solid $border-color;
...@@ -319,29 +353,25 @@ ...@@ -319,29 +353,25 @@
.count-badge-count { .count-badge-count {
padding: 0 12px; padding: 0 12px;
border-right: 0;
border-radius: $border-radius-base 0 0 $border-radius-base;
background: $gray-light; background: $gray-light;
border-radius: 0 $border-radius-base $border-radius-base 0;
} }
.count-badge-button { .count-badge-button {
border-radius: 0 $border-radius-base $border-radius-base 0; border-right: 0;
border-radius: $border-radius-base 0 0 $border-radius-base;
} }
} }
.project-clone-holder { .project-clone-holder {
display: inline-block; display: inline-block;
margin: $gl-padding $gl-padding-8 0 0; margin: $gl-padding 0 0;
input { input {
height: $input-height; height: $input-height;
} }
} }
.clone-dropdown-btn {
background-color: $white-light;
}
.clone-options-dropdown { .clone-options-dropdown {
min-width: 240px; min-width: 240px;
...@@ -355,6 +385,31 @@ ...@@ -355,6 +385,31 @@
} }
} }
.project-repo-buttons {
.icon {
top: 0;
}
.count-badge,
.btn-xs {
height: 24px;
}
.dropdown-toggle,
.clone-dropdown-btn {
.fa {
color: unset;
}
}
.btn {
.notifications-icon {
top: 1px;
margin-right: 0;
}
}
}
.split-one { .split-one {
display: inline-table; display: inline-table;
margin-right: 12px; margin-right: 12px;
...@@ -715,10 +770,10 @@ ...@@ -715,10 +770,10 @@
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
} }
.project-stats { .project-stats,
.project-buttons {
font-size: 0; font-size: 0;
text-align: center; text-align: center;
border-bottom: 1px solid $border-color;
.scrolling-tabs-container { .scrolling-tabs-container {
.scrolling-tabs { .scrolling-tabs {
...@@ -786,23 +841,43 @@ ...@@ -786,23 +841,43 @@
font-size: $gl-font-size; font-size: $gl-font-size;
line-height: $gl-btn-line-height; line-height: $gl-btn-line-height;
color: $gl-text-color-secondary; color: $gl-text-color-secondary;
white-space: nowrap; white-space: pre-wrap;
} }
.stat-link { .stat-link {
border-bottom: 0; border-bottom: 0;
color: $black;
&:hover, &:hover,
&:focus { &:focus {
color: $gl-text-color;
text-decoration: underline; text-decoration: underline;
border-bottom: 0; border-bottom: 0;
} }
.project-stat-value {
color: $gl-text-color;
}
.icon {
color: $gl-text-color-secondary;
}
.add-license-link {
&,
.icon {
color: $blue-600;
}
}
} }
.btn { .btn {
padding: $gl-btn-vert-padding $gl-btn-horz-padding; margin-top: $gl-padding;
padding: $gl-btn-vert-padding $gl-btn-padding;
line-height: $gl-btn-line-height; line-height: $gl-btn-line-height;
.icon {
top: 0;
}
} }
.btn-missing { .btn-missing {
...@@ -811,6 +886,13 @@ ...@@ -811,6 +886,13 @@
} }
} }
.project-buttons {
.stat-text {
@extend .btn;
@extend .btn-default;
}
}
.repository-languages-bar { .repository-languages-bar {
height: 8px; height: 8px;
margin-bottom: $gl-padding-8; margin-bottom: $gl-padding-8;
...@@ -934,8 +1016,6 @@ pre.light-well { ...@@ -934,8 +1016,6 @@ pre.light-well {
} }
.git-clone-holder { .git-clone-holder {
width: 320px;
.btn-clipboard { .btn-clipboard {
border: 1px solid $border-color; border: 1px solid $border-color;
} }
...@@ -958,6 +1038,15 @@ pre.light-well { ...@@ -958,6 +1038,15 @@ pre.light-well {
} }
} }
.git-clone-holder,
.mobile-git-clone {
.btn {
.icon {
fill: $white;
}
}
}
.cannot-be-merged, .cannot-be-merged,
.cannot-be-merged:hover { .cannot-be-merged:hover {
color: $red-500; color: $red-500;
......
...@@ -16,8 +16,12 @@ class NotificationSettingsController < ApplicationController ...@@ -16,8 +16,12 @@ class NotificationSettingsController < ApplicationController
@notification_setting = current_user.notification_settings.find(params[:id]) @notification_setting = current_user.notification_settings.find(params[:id])
@saved = @notification_setting.update(notification_setting_params_for(@notification_setting.source)) @saved = @notification_setting.update(notification_setting_params_for(@notification_setting.source))
if params[:hide_label].present?
render_response("projects/buttons/_notifications")
else
render_response render_response
end end
end
private private
...@@ -37,9 +41,9 @@ class NotificationSettingsController < ApplicationController ...@@ -37,9 +41,9 @@ class NotificationSettingsController < ApplicationController
can?(current_user, ability_name, resource) can?(current_user, ability_name, resource)
end end
def render_response def render_response(response_template = "shared/notifications/_button")
render json: { render json: {
html: view_to_html_string("shared/notifications/_button", notification_setting: @notification_setting), html: view_to_html_string(response_template, notification_setting: @notification_setting),
saved: @saved saved: @saved
} }
end end
......
...@@ -85,13 +85,14 @@ module ButtonHelper ...@@ -85,13 +85,14 @@ module ButtonHelper
dropdown_item_with_description('SSH', dropdown_description, href: append_url, data: { clone_type: 'ssh' }) dropdown_item_with_description('SSH', dropdown_description, href: append_url, data: { clone_type: 'ssh' })
end end
def dropdown_item_with_description(title, description, href: nil, data: nil) def dropdown_item_with_description(title, description, href: nil, data: nil, default: false)
active_class = "is-active" if default
button_content = content_tag(:strong, title, class: 'dropdown-menu-inner-title') button_content = content_tag(:strong, title, class: 'dropdown-menu-inner-title')
button_content << content_tag(:span, description, class: 'dropdown-menu-inner-content') if description button_content << content_tag(:span, description, class: 'dropdown-menu-inner-content') if description
content_tag (href ? :a : :span), content_tag (href ? :a : :span),
(href ? button_content : title), (href ? button_content : title),
class: "#{title.downcase}-selector", class: "#{title.downcase}-selector #{active_class}",
href: (href if href), href: (href if href),
data: (data if data) data: (data if data)
end end
......
...@@ -140,7 +140,7 @@ module VisibilityLevelHelper ...@@ -140,7 +140,7 @@ module VisibilityLevelHelper
end end
def project_visibility_icon_description(level) def project_visibility_icon_description(level)
"#{project_visibility_level_description(level)}" "#{visibility_level_label(level)} - #{project_visibility_level_description(level)}"
end end
def visibility_level_label(level) def visibility_level_label(level)
......
This diff is collapsed.
.group-home-panel.text-center .group-home-panel.text-center.border-bottom
%div{ class: container_class } %div{ class: container_class }
.avatar-container.s70.group-avatar .avatar-container.s70.group-avatar
= group_icon(@group, class: "avatar s70 avatar-tile") = group_icon(@group, class: "avatar s70 avatar-tile")
......
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
- commit = local_assigns.fetch(:commit) { @repository.commit } - commit = local_assigns.fetch(:commit) { @repository.commit }
- ref = local_assigns.fetch(:ref) { current_ref } - ref = local_assigns.fetch(:ref) { current_ref }
- project = local_assigns.fetch(:project) { @project } - project = local_assigns.fetch(:project) { @project }
- content_url = local_assigns.fetch(:content_url) { @tree.readme ? project_blob_path(@project, tree_join(@ref, @tree.readme.path)) : project_tree_path(@project, @ref) } - content_url = local_assigns.fetch(:content_url) { @tree.readme ? project_blob_path(@project, tree_join(@ref, @tree.readme.path)) : project_tree_path(@project, @ref) }
- show_auto_devops_callout = show_auto_devops_callout?(@project)
#tree-holder.tree-holder.clearfix #tree-holder.tree-holder.clearfix
.nav-block .nav-block
...@@ -10,4 +12,8 @@ ...@@ -10,4 +12,8 @@
- if commit - if commit
= render 'shared/commit_well', commit: commit, ref: ref, project: project = render 'shared/commit_well', commit: commit, ref: ref, project: project
- if is_project_overview
.project-buttons.append-bottom-default
= render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout)
= render 'projects/tree/tree_content', tree: @tree, content_url: content_url = render 'projects/tree/tree_content', tree: @tree, content_url: content_url
- empty_repo = @project.empty_repo? - empty_repo = @project.empty_repo?
- license = @project.license_anchor_data - show_auto_devops_callout = show_auto_devops_callout?(@project)
.project-home-panel{ class: ("empty-project" if empty_repo) } .project-home-panel{ class: ("empty-project" if empty_repo) }
.limit-container-width{ class: container_class } .project-header.row.append-bottom-8
.project-header.d-flex.flex-row.flex-wrap.align-items-center.append-bottom-8 .project-title-row.col-md-12.col-lg-7.d-flex
.project-title-row.d-flex.align-items-center
.avatar-container.project-avatar.float-none .avatar-container.project-avatar.float-none
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s24', width: 24, height: 24) = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64)
%h1.project-title.d-flex.align-items-baseline.qa-project-name .d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline
%h1.project-title.qa-project-name
= @project.name = @project.name
.project-metadata.d-flex.flex-row.flex-wrap.align-items-baseline %span.project-visibility.prepend-left-8.d-inline-flex.align-items-baseline.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
.project-visibility.d-inline-flex.align-items-baseline.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
= visibility_level_icon(@project.visibility_level, fw: false, options: {class: 'icon'}) = visibility_level_icon(@project.visibility_level, fw: false, options: {class: 'icon'})
= visibility_level_label(@project.visibility_level) .project-metadata.d-flex.align-items-center
- if license.present? - if can?(current_user, :read_project, @project)
.project-license.d-inline-flex.align-items-baseline %span.text-secondary
= link_to_if license.link, sprite_icon('scale', size: 16, css_class: 'icon') + license.label, license.link, class: license.enabled ? 'btn btn-link btn-secondary-hover-link' : 'btn btn-link' = s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
- if current_user
%span.access-request-links.prepend-left-8
= render 'shared/members/access_request_links', source: @project
- if @project.tag_list.present? - if @project.tag_list.present?
.project-tag-list.d-inline-flex.align-items-baseline.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_tags? ? @project.tag_list.join(', ') : nil } %span.project-tag-list.d-inline-flex.prepend-left-8.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_tags? ? @project.tag_list.join(', ') : nil }
= sprite_icon('tag', size: 16, css_class: 'icon') = sprite_icon('tag', size: 16, css_class: 'icon append-right-4')
= @project.tags_to_show = @project.tags_to_show
- if @project.has_extra_tags? - if @project.has_extra_tags?
= _("+ %{count} more") % { count: @project.count_of_extra_tags_not_shown } = _("+ %{count} more") % { count: @project.count_of_extra_tags_not_shown }
.project-home-desc .project-repo-buttons.col-md-12.col-lg-5.d-inline-flex.flex-wrap.justify-content-lg-end
- if current_user
.d-inline-flex
= render 'projects/buttons/notifications', notification_setting: @notification_setting, btn_class: 'btn-xs'
.count-buttons.d-inline-flex
= render 'projects/buttons/star'
= render 'projects/buttons/fork'
- if can?(current_user, :download_code, @project)
.project-clone-holder.d-inline-flex.d-md-none.btn-block
= render "shared/mobile_clone_panel"
.project-clone-holder.d-none.d-md-inline-flex
= render "projects/buttons/clone"
- if can?(current_user, :download_code, @project)
%nav.project-stats
.nav-links.quick-links.mt-3
= render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
.project-home-desc.mt-1
- if @project.description.present? - if @project.description.present?
.project-description .project-description
.project-description-markdown.read-more-container .project-description-markdown.read-more-container
= markdown_field(@project, :description) = markdown_field(@project, :description)
%button.btn.btn-blank.btn-link.text-secondary.js-read-more-trigger.text-secondary.d-lg-none{ type: "button" } %button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more") = _("Read more")
- if can?(current_user, :read_project, @project)
.text-secondary.prepend-top-8
= s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
- if @project.forked? - if @project.forked?
%p %p
- if @project.fork_source - if @project.fork_source
...@@ -52,7 +72,7 @@ ...@@ -52,7 +72,7 @@
= render "shared/mirror_status" = render "shared/mirror_status"
- if @project.badges.present? - if @project.badges.present?
.project-badges.prepend-top-default.append-bottom-default .project-badges.mb-2
- @project.badges.each do |badge| - @project.badges.each do |badge|
%a.append-right-8{ href: badge.rendered_link_url(@project), %a.append-right-8{ href: badge.rendered_link_url(@project),
target: '_blank', target: '_blank',
...@@ -60,31 +80,3 @@ ...@@ -60,31 +80,3 @@
%img.project-badge{ src: badge.rendered_image_url(@project), %img.project-badge{ src: badge.rendered_image_url(@project),
'aria-hidden': true, 'aria-hidden': true,
alt: 'Project badge' }> alt: 'Project badge' }>
.project-repo-buttons.d-inline-flex.flex-wrap
.count-buttons.d-inline-flex
= render 'projects/buttons/star'
= render 'projects/buttons/fork'
- if can?(current_user, :download_code, @project)
.project-clone-holder.d-inline-flex.d-sm-none
= render "shared/mobile_clone_panel"
.project-clone-holder.d-none.d-sm-inline-flex
= render "shared/clone_panel"
- if show_xcode_link?(@project)
.project-action-button.project-xcode.inline
= render "projects/buttons/xcode_link"
- if current_user
- if can?(current_user, :download_code, @project)
.d-none.d-sm-inline-flex
= render 'projects/buttons/download', project: @project, ref: @ref
.d-none.d-sm-inline-flex
= render 'projects/buttons/dropdown'
.d-none.d-sm-inline-flex
= render 'shared/notifications/button', notification_setting: @notification_setting
.d-none.d-sm-inline-flex
= render 'shared/members/access_request_buttons', source: @project
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
%ul.nav %ul.nav
- anchors.each do |anchor| - anchors.each do |anchor|
%li.nav-item %li.nav-item
= link_to_if anchor.link, anchor.label, anchor.link, class: anchor.enabled ? 'nav-link stat-link' : "nav-link btn btn-#{anchor.class_modifier || 'missing'}" do = link_to_if anchor.link, anchor.label, anchor.link, class: anchor.is_link ? 'nav-link stat-link d-flex align-items-center' : "nav-link btn btn-#{anchor.class_modifier || 'missing'} d-flex align-items-center" do
.stat-text= anchor.label .stat-text.d-flex.align-items-center= anchor.label
- project = project || @project
.git-clone-holder.js-git-clone-holder.input-group
- if allowed_protocols_present?
.input-group-text.clone-dropdown-btn.btn
%span.js-clone-dropdown-label
= enabled_project_button(project, enabled_protocol)
- else
%a#clone-dropdown.input-group-text.btn.btn-primary.btn-xs.clone-dropdown-btn.qa-clone-dropdown{ href: '#', data: { toggle: 'dropdown' } }
%span.append-right-4.js-clone-dropdown-label
= _('Clone')
= sprite_icon("arrow-down", css_class: "icon")
%form.p-3.dropdown-menu.dropdown-menu-right.dropdown-menu-large.dropdown-menu-selectable.clone-options-dropdown
%li.pb-2
%label.label-bold
= _('Clone with SSH')
.input-group
= text_field_tag :ssh_project_clone, project.ssh_url_to_repo, class: "js-select-on-focus form-control", readonly: true, aria: { label: 'Project clone URL' }
.input-group-append
= clipboard_button(target: '#ssh_project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
= render_if_exists 'projects/buttons/geo'
%li
%label.label-bold
= _('Clone with %{http_label}') % { http_label: gitlab_config.protocol.upcase }
.input-group
= text_field_tag :http_project_clone, project.http_url_to_repo, class: "js-select-on-focus form-control", readonly: true, aria: { label: 'Project clone URL' }
.input-group-append
= clipboard_button(target: '#http_project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
= render_if_exists 'projects/buttons/geo'
= render_if_exists 'shared/geo_info_modal', project: project
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
.project-action-button.dropdown.inline> .project-action-button.dropdown.inline>
%button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static' } %button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static' }
= sprite_icon('download') = sprite_icon('download')
= icon("caret-down")
%span.sr-only= _('Select Archive Format') %span.sr-only= _('Select Archive Format')
= sprite_icon("arrow-down")
%ul.dropdown-menu.dropdown-menu-right{ role: 'menu' } %ul.dropdown-menu.dropdown-menu-right{ role: 'menu' }
%li.dropdown-header %li.dropdown-header
#{ _('Source code') } #{ _('Source code') }
......
- unless @project.empty_repo? - unless @project.empty_repo?
- if current_user && can?(current_user, :fork_project, @project) - if current_user && can?(current_user, :fork_project, @project)
.count-badge.d-inline-flex.align-item-stretch.append-right-8 .count-badge.d-inline-flex.align-item-stretch.append-right-8
%span.fork-count.count-badge-count.d-flex.align-items-center
= link_to project_forks_path(@project), title: n_(s_('ProjectOverview|Fork'), s_('ProjectOverview|Forks'), @project.forks_count), class: 'count' do
= @project.forks_count
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: s_('ProjectOverview|Go to your fork'), class: 'btn btn-default has-tooltip count-badge-button d-flex align-items-center fork-btn' do = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: s_('ProjectOverview|Go to your fork'), class: 'btn btn-default has-tooltip count-badge-button d-flex align-items-center fork-btn' do
= sprite_icon('fork', { css_class: 'icon' }) = sprite_icon('fork', { css_class: 'icon' })
...@@ -15,3 +12,6 @@ ...@@ -15,3 +12,6 @@
title: (s_('ProjectOverview|You have reached your project limit') unless can_create_fork) do title: (s_('ProjectOverview|You have reached your project limit') unless can_create_fork) do
= sprite_icon('fork', { css_class: 'icon' }) = sprite_icon('fork', { css_class: 'icon' })
%span= s_('ProjectOverview|Fork') %span= s_('ProjectOverview|Fork')
%span.fork-count.count-badge-count.d-flex.align-items-center
= link_to project_forks_path(@project), title: n_(s_('ProjectOverview|Fork'), s_('ProjectOverview|Forks'), @project.forks_count), class: 'count' do
= @project.forks_count
- btn_class = local_assigns.fetch(:btn_class, "btn-xs")
- if notification_setting
.js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f|
= hidden_setting_source_input(notification_setting)
= hidden_field_tag "hide_label", true
= f.hidden_field :level, class: "notification_setting_level"
.js-notification-toggle-btns
%div{ class: ("btn-group" if notification_setting.custom?) }
- if notification_setting.custom?
%button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
= sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
%span.js-notification-loading.fa.hidden
%button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= sprite_icon("arrow-down", css_class: "icon")
.sr-only Toggle dropdown
- else
%button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting - #{notification_title(notification_setting.level)}", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
%span.js-notification-loading.fa.hidden
= sprite_icon("arrow-down", css_class: "icon")
= render "shared/notifications/notification_dropdown", notification_setting: notification_setting
= content_for :scripts_body do
= render "shared/notifications/custom_notifications", notification_setting: notification_setting
- if current_user - if current_user
.count-badge.d-inline-flex.align-item-stretch.append-right-8 .count-badge.d-inline-flex.align-item-stretch.append-right-8
%span.star-count.count-badge-count.d-flex.align-items-center %button.count-badge-button.btn.btn-default.btn-xs.d-flex.align-items-center.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(@project, :json) } }
= @project.star_count
%button.count-badge-button.btn.btn-default.d-flex.align-items-center.star-btn.toggle-star{ type: "button", data: { endpoint: toggle_star_project_path(@project, :json) } }
- if current_user.starred?(@project) - if current_user.starred?(@project)
= sprite_icon('star', { css_class: 'icon' }) = sprite_icon('star', { css_class: 'icon' })
%span.starred= s_('ProjectOverview|Unstar') %span.starred= s_('ProjectOverview|Unstar')
- else - else
= sprite_icon('star-o', { css_class: 'icon' }) = sprite_icon('star-o', { css_class: 'icon' })
%span= s_('ProjectOverview|Star') %span= s_('ProjectOverview|Star')
%span.star-count.count-badge-count.d-flex.align-items-center
= @project.star_count
- else - else
.count-badge.d-inline-flex.align-item-stretch.append-right-8 .count-badge.d-inline-flex.align-item-stretch.append-right-8
%span.star-count.count-badge-count.d-flex.align-items-center = link_to new_user_session_path, class: 'btn btn-default btn-xs has-tooltip count-badge-button d-flex align-items-center star-btn', title: s_('ProjectOverview|You must sign in to star a project') do
= @project.star_count
= link_to new_user_session_path, class: 'btn btn-default has-tooltip count-badge-button d-flex align-items-center star-btn', title: s_('ProjectOverview|You must sign in to star a project') do
= sprite_icon('star-o', { css_class: 'icon' }) = sprite_icon('star-o', { css_class: 'icon' })
%span= s_('ProjectOverview|Star') %span= s_('ProjectOverview|Star')
%span.star-count.count-badge-count.d-flex.align-items-center
= @project.star_count
...@@ -4,11 +4,10 @@ ...@@ -4,11 +4,10 @@
= render partial: 'flash_messages', locals: { project: @project } = render partial: 'flash_messages', locals: { project: @project }
= render "home_panel" %div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
= render "home_panel"
.project-empty-note-panel .project-empty-note-panel
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
.prepend-top-20
%h4.append-bottom-20 %h4.append-bottom-20
= _('The repository for this project is empty') = _('The repository for this project is empty')
...@@ -32,30 +31,29 @@ ...@@ -32,30 +31,29 @@
= _('Otherwise it is recommended you start with one of the options below.') = _('Otherwise it is recommended you start with one of the options below.')
.prepend-top-20 .prepend-top-20
%nav.project-stats{ class: [container_class, ("limit-container-width" unless fluid_layout)] } %nav.project-buttons
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller .scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left') .fade-left= icon('angle-left')
.fade-right= icon('angle-right') .fade-right= icon('angle-right')
.nav-links.scrolling-tabs.quick-links .nav-links.scrolling-tabs.quick-links
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons = render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
- if can?(current_user, :push_code, @project) - if can?(current_user, :push_code, @project)
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] } %div
.prepend-top-20 .prepend-top-20
.empty_wrapper .empty_wrapper
%h3#repo-command-line-instructions.page-title-empty %h3#repo-command-line-instructions.page-title-empty
Command line instructions = _('Command line instructions')
.git-empty.js-git-empty .git-empty.js-git-empty
%fieldset %fieldset
%h5 Git global setup %h5= _('Git global setup')
%pre.bg-light %pre.bg-light
:preserve :preserve
git config --global user.name "#{h git_user_name}" git config --global user.name "#{h git_user_name}"
git config --global user.email "#{h git_user_email}" git config --global user.email "#{h git_user_email}"
%fieldset %fieldset
%h5 Create a new repository %h5= _('Create a new repository')
%pre.bg-light %pre.bg-light
:preserve :preserve
git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')} git clone #{ content_tag(:span, default_url_to_repo, class: 'js-clone')}
...@@ -68,7 +66,7 @@ ...@@ -68,7 +66,7 @@
git push -u origin master git push -u origin master
%fieldset %fieldset
%h5 Existing folder %h5= _('Existing folder')
%pre.bg-light %pre.bg-light
:preserve :preserve
cd existing_folder cd existing_folder
...@@ -81,7 +79,7 @@ ...@@ -81,7 +79,7 @@
git push -u origin master git push -u origin master
%fieldset %fieldset
%h5 Existing Git repository %h5= _('Existing Git repository')
%pre.bg-light %pre.bg-light
:preserve :preserve
cd existing_repo cd existing_repo
...@@ -94,4 +92,4 @@ ...@@ -94,4 +92,4 @@
- if can? current_user, :remove_project, @project - if can? current_user, :remove_project, @project
.prepend-top-20 .prepend-top-20
= link_to 'Remove project', [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-inverted btn-remove float-right" = link_to _('Remove project'), [@project.namespace.becomes(Namespace), @project], data: { confirm: remove_project_message(@project)}, method: :delete, class: "btn btn-inverted btn-remove float-right"
- @no_container = true - @no_container = true
- breadcrumb_title _("Details") - breadcrumb_title _("Details")
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
- show_auto_devops_callout = show_auto_devops_callout?(@project)
= content_for :meta_tags do = content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity") = auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
...@@ -15,20 +14,11 @@ ...@@ -15,20 +14,11 @@
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] } %div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
= render "projects/last_push" = render "projects/last_push"
= render "home_panel" = render "home_panel"
- if can?(current_user, :download_code, @project)
%nav.project-stats{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
.nav-links.scrolling-tabs.quick-links
= render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
= render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout)
- if can?(current_user, :download_code, @project) && @project.repository_languages.present?
= repository_languages_bar(@project.repository_languages) = repository_languages_bar(@project.repository_languages)
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
- if @project.archived? - if @project.archived?
.text-warning.center.prepend-top-20 .text-warning.center.prepend-top-20
%p %p
...@@ -41,4 +31,4 @@ ...@@ -41,4 +31,4 @@
= render 'shared/auto_devops_callout' = render 'shared/auto_devops_callout'
%div{ class: project_child_container_class(view_path) } %div{ class: project_child_container_class(view_path) }
= render view_path = render view_path, is_project_overview: true
...@@ -87,4 +87,8 @@ ...@@ -87,4 +87,8 @@
= link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default qa-web-ide-button' do = link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default qa-web-ide-button' do
= _('Web IDE') = _('Web IDE')
- if show_xcode_link?(@project)
.project-action-button.project-xcode.inline
= render "projects/buttons/xcode_link"
= render 'projects/buttons/download', project: @project, ref: @ref = render 'projects/buttons/download', project: @project, ref: @ref
...@@ -24,6 +24,6 @@ ...@@ -24,6 +24,6 @@
.input-group-append .input-group-append
= clipboard_button(target: '#project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard") = clipboard_button(target: '#project_clone', title: _("Copy URL to clipboard"), class: "input-group-text btn-default btn-clipboard")
= geo_button(modal_target: '#modal-geo-info') if Gitlab::Geo.secondary? = geo_button(modal_target: '#modal-geo-info')
= render 'shared/geo_info_modal', project: project if Gitlab::Geo.secondary? = render 'shared/geo_info_modal', project: project if Gitlab::Geo.secondary?
- project = project || @project - project = project || @project
- ssh_copy_label = _("Copy SSH clone URL") - ssh_copy_label = _("Copy SSH clone URL")
- http_copy_label = _("Copy HTTPS clone URL") - http_copy_label = _('Copy %{http_label} clone URL') % { http_label: gitlab_config.protocol.upcase }
.btn-group.mobile-git-clone.js-mobile-git-clone .btn-group.mobile-git-clone.js-mobile-git-clone.btn-block
= clipboard_button(button_text: default_clone_label, target: '#project_clone', hide_button_icon: true, class: "input-group-text clone-dropdown-btn js-clone-dropdown-label btn btn-default") = clipboard_button(button_text: default_clone_label, text: default_url_to_repo(project), hide_button_icon: true, class: "btn-primary flex-fill bold justify-content-center input-group-text clone-dropdown-btn js-clone-dropdown-label")
%button.btn.btn-default.dropdown-toggle.js-dropdown-toggle{ type: "button", data: { toggle: "dropdown" } } %button.btn.btn-primary.dropdown-toggle.js-dropdown-toggle{ type: "button", data: { toggle: "dropdown" } }
= icon("caret-down", class: "dropdown-btn-icon") = sprite_icon("arrow-down", css_class: "dropdown-btn-icon icon")
%ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown{ data: { dropdown: true } } %ul.dropdown-menu.dropdown-menu-selectable.dropdown-menu-right.clone-options-dropdown{ data: { dropdown: true } }
%li %li
= dropdown_item_with_description(ssh_copy_label, project.ssh_url_to_repo, href: project.ssh_url_to_repo, data: { clone_type: 'ssh' }) = dropdown_item_with_description(ssh_copy_label, project.ssh_url_to_repo, href: project.ssh_url_to_repo, data: { clone_type: 'ssh' }, default: true)
%li %li
= dropdown_item_with_description(http_copy_label, project.http_url_to_repo, href: project.http_url_to_repo, data: { clone_type: 'http' }) = dropdown_item_with_description(http_copy_label, project.http_url_to_repo, href: project.http_url_to_repo, data: { clone_type: 'http' })
- model_name = source.model_name.to_s.downcase
- if can?(current_user, :"destroy_#{model_name}_member", source.members.find_by(user_id: current_user.id)) # rubocop: disable CodeReuse/ActiveRecord
- link_text = source.is_a?(Group) ? _('Leave group') : _('Leave project')
= link_to link_text, polymorphic_path([:leave, source, :members]),
method: :delete,
data: { confirm: leave_confirmation_message(source) },
class: 'access-request-link'
- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord
= link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
method: :delete,
data: { confirm: remove_member_message(requester) },
class: 'access-request-link'
- elsif source.request_access_enabled && can?(current_user, :request_access, source)
= link_to _('Request Access'), polymorphic_path([:request_access, source, :members]),
method: :post,
class: 'access-request-link'
- btn_class = local_assigns.fetch(:btn_class, nil)
- if notification_setting - if notification_setting
.js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline .js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form" } do |f| = form_for notification_setting, remote: true, html: { class: "inline notification-form" } do |f|
...@@ -6,14 +8,14 @@ ...@@ -6,14 +8,14 @@
.js-notification-toggle-btns .js-notification-toggle-btns
%div{ class: ("btn-group" if notification_setting.custom?) } %div{ class: ("btn-group" if notification_setting.custom?) }
- if notification_setting.custom? - if notification_setting.custom?
%button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } } %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting"), class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
= icon("bell", class: "js-notification-loading") = icon("bell", class: "js-notification-loading")
= notification_title(notification_setting.level) = notification_title(notification_setting.level)
%button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= icon('caret-down') = icon('caret-down')
.sr-only Toggle dropdown .sr-only Toggle dropdown
- else - else
%button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= icon("bell", class: "js-notification-loading") = icon("bell", class: "js-notification-loading")
= notification_title(notification_setting.level) = notification_title(notification_setting.level)
= icon("caret-down") = icon("caret-down")
......
---
title: Design improvements to project overview page
merge_request: 22196
author:
type: changed
...@@ -5,22 +5,8 @@ export default () => { ...@@ -5,22 +5,8 @@ export default () => {
if (!$modal.length) return; if (!$modal.length) return;
$modal $modal.appendTo('body').modal({
.appendTo('body')
.modal({
modal: true, modal: true,
show: false, show: false,
})
.on('show.bs.modal', e => {
const { cloneUrlPrimary, cloneUrlSecondary } = $(e.currentTarget).data();
$('#geo-info-1').val(
`git clone ${cloneUrlSecondary || '<clone url for secondary repository>'}`,
);
$('#geo-info-2').val(
`git remote set-url --push origin ${cloneUrlPrimary ||
'<clone url for primary repository>'}`,
);
}); });
}; };
...@@ -4,19 +4,19 @@ module EE ...@@ -4,19 +4,19 @@ module EE
module ProjectPresenter module ProjectPresenter
extend ::Gitlab::Utils::Override extend ::Gitlab::Utils::Override
override :statistics_anchors override :statistics_buttons
def statistics_anchors(show_auto_devops_callout:) def statistics_buttons(show_auto_devops_callout:)
super + extra_statistics_anchors super + extra_statistics_buttons
end end
def extra_statistics_anchors def extra_statistics_buttons
anchors = [] buttons = []
if can?(current_user, :read_project_security_dashboard, project) if can?(current_user, :read_project_security_dashboard, project)
anchors << security_dashboard_data buttons << security_dashboard_data
end end
anchors buttons
end end
def approver_groups def approver_groups
...@@ -26,9 +26,10 @@ module EE ...@@ -26,9 +26,10 @@ module EE
private private
def security_dashboard_data def security_dashboard_data
OpenStruct.new(enabled: true, OpenStruct.new(is_link: false,
label: _('Security Dashboard'), label: statistic_icon('lock') + _('Security Dashboard'),
link: project_security_dashboard_path(project)) link: project_security_dashboard_path(project),
class_modifier: 'default')
end end
end end
end end
- if Gitlab::Geo.secondary?
= geo_button(modal_target: '#modal-geo-info')
#modal-geo-info.modal.in{ tabindex: '-1', data: { clone_url_secondary: h(default_url_to_repo(project)), clone_url_primary: h(geo_primary_default_url_to_repo(project)) } } - if Gitlab::Geo.secondary?
#modal-geo-info.modal.in{ tabindex: '-1' }
.modal-dialog .modal-dialog
.modal-content .modal-content
.modal-header .modal-header
...@@ -9,11 +10,30 @@ ...@@ -9,11 +10,30 @@
%p %p
%strong= 'Step 1.' %strong= 'Step 1.'
Clone the repository from your secondary node: Clone the repository from your secondary node:
- if project.ssh_url_to_repo.present?
%p
%strong= 'SSH'
.form-group
.input-group
%input#geo-info-1-ssh.form-control{ value: "git clone " + project.ssh_url_to_repo, readonly: "readonly" }
.input-group-append
= clipboard_button(target: '#geo-info-1-ssh', class: "btn-default", container: "#modal-geo-info")
- if project.http_url_to_repo.present?
%p
%strong= 'HTTP'
.form-group
.input-group
%input#geo-info-1-http.form-control{ value: "git clone " + project.http_url_to_repo, readonly: "readonly" }
.input-group-append
= clipboard_button(target: '#geo-info-1-http', class: "btn-default", container: "#modal-geo-info")
- if alternative_kerberos_url?
%p
%strong= 'Kerberos'
.form-group .form-group
.input-group .input-group
%input#geo-info-1.form-control{ value: "git clone " + default_url_to_repo(), readonly: "readonly" } %input#geo-info-1-kerberos.form-control{ value: "git clone " + project.kerberos_url_to_repo, readonly: "readonly" }
.input-group-append .input-group-append
= clipboard_button(target: '#geo-info-1', class: "btn-default", container: "#modal-geo-info") = clipboard_button(target: '#geo-info-1-kerberos', class: "btn-default", container: "#modal-geo-info")
%p %p
%strong= 'Step 2.' %strong= 'Step 2.'
Go to the new directory and define Go to the new directory and define
...@@ -21,6 +41,24 @@ ...@@ -21,6 +41,24 @@
repository URL as the repository URL as the
%strong= 'push' %strong= 'push'
remote: remote:
- if geo_primary_ssh_url_to_repo(project).present? or geo_primary_http_url_to_repo(project).present?
- if geo_primary_ssh_url_to_repo(project).present?
%p
%strong= 'SSH'
.form-group
.input-group
%input#geo-info-2-ssh.form-control{ value: "git remote set-url --push origin " + geo_primary_ssh_url_to_repo(project), readonly: "readonly" }
.input-group-append
= clipboard_button(target: '#geo-info-2-ssh', class: "btn-default", container: "#modal-geo-info")
- if geo_primary_http_url_to_repo(project).present?
%p
%strong= 'HTTP'
.form-group
.input-group
%input#geo-info-2-http.form-control{ value: "git remote set-url --push origin " + geo_primary_http_url_to_repo(project), readonly: "readonly" }
.input-group-append
= clipboard_button(target: '#geo-info-2-http', class: "btn-default", container: "#modal-geo-info")
- else
.form-group .form-group
.input-group .input-group
%input#geo-info-2.form-control{ value: "git remote set-url --push origin &lt;clone url for primary repository&gt;", readonly: "readonly" } %input#geo-info-2.form-control{ value: "git remote set-url --push origin &lt;clone url for primary repository&gt;", readonly: "readonly" }
......
...@@ -23,20 +23,12 @@ describe 'Geo clone instructions', :js do ...@@ -23,20 +23,12 @@ describe 'Geo clone instructions', :js do
create(:personal_key, user: developer) create(:personal_key, user: developer)
end end
it 'defaults to SSH' do it 'displays clone instructions' do
visit_project visit_project
show_geo_clone_instructions show_geo_clone_instructions
expect_instructions_for('ssh') expect_instructions_for('ssh')
end
it 'switches to HTTP' do
visit_project
select_protocol('HTTP')
show_geo_clone_instructions
expect_instructions_for('http') expect_instructions_for('http')
end end
end end
...@@ -45,13 +37,9 @@ describe 'Geo clone instructions', :js do ...@@ -45,13 +37,9 @@ describe 'Geo clone instructions', :js do
visit project_path(project) visit project_path(project)
end end
def select_protocol(protocol)
find('#clone-dropdown').click
find(".#{protocol.downcase}-selector").click
end
def show_geo_clone_instructions def show_geo_clone_instructions
find('.btn-geo').click find('.qa-clone-dropdown').click
find('.btn-geo', match: :first).click
end end
def expect_instructions_for(protocol) def expect_instructions_for(protocol)
...@@ -59,9 +47,9 @@ describe 'Geo clone instructions', :js do ...@@ -59,9 +47,9 @@ describe 'Geo clone instructions', :js do
secondary_remote = secondary_url(protocol) secondary_remote = secondary_url(protocol)
expect(page).to have_content('How to work faster with Geo') expect(page).to have_content('How to work faster with Geo')
expect(page.find('#geo-info-1').value).to eq "git clone #{secondary_remote}" expect(page.find("#geo-info-1-#{protocol}").value).to eq "git clone #{secondary_remote}"
# the primary_url does not return the full url, but just the part up to the host: # the primary_url does not return the full url, but just the part up to the host:
expect(page.find('#geo-info-2').value).to start_with("git remote set-url --push origin #{primary_remote}") expect(page.find("#geo-info-2-#{protocol}").value).to start_with("git remote set-url --push origin #{primary_remote}")
end end
def primary_url(protocol) def primary_url(protocol)
......
...@@ -21,7 +21,7 @@ describe 'Project show page', :feature do ...@@ -21,7 +21,7 @@ describe 'Project show page', :feature do
visit project_path(project) visit project_path(project)
page.within('.project-stats') do page.within('.project-buttons') do
expect(page).to have_link('Kubernetes configured', href: project_clusters_path(project)) expect(page).to have_link('Kubernetes configured', href: project_clusters_path(project))
end end
end end
......
...@@ -7,15 +7,16 @@ describe ProjectPresenter do ...@@ -7,15 +7,16 @@ describe ProjectPresenter do
let(:user) { create(:user) } let(:user) { create(:user) }
describe '#extra_statistics_anchors' do describe '#extra_statistics_buttons' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:pipeline) { create(:ci_pipeline, project: project) } let(:pipeline) { create(:ci_pipeline, project: project) }
let(:presenter) { described_class.new(project, current_user: user) } let(:presenter) { described_class.new(project, current_user: user) }
let(:security_dashboard_data) do let(:security_dashboard_data) do
OpenStruct.new(enabled: true, OpenStruct.new(is_link: false,
label: _('Security Dashboard'), label: a_string_including('Security Dashboard'),
link: project_security_dashboard_path(project)) link: project_security_dashboard_path(project),
class_modifier: 'default')
end end
context 'user is allowed to read security dashboard' do context 'user is allowed to read security dashboard' do
...@@ -24,7 +25,7 @@ describe ProjectPresenter do ...@@ -24,7 +25,7 @@ describe ProjectPresenter do
end end
it 'has security dashboard link' do it 'has security dashboard link' do
expect(presenter.extra_statistics_anchors).to include(security_dashboard_data) expect(presenter.extra_statistics_buttons.find { |button| button[:link] == project_security_dashboard_path(project) }).not_to be_nil
end end
end end
...@@ -34,7 +35,7 @@ describe ProjectPresenter do ...@@ -34,7 +35,7 @@ describe ProjectPresenter do
end end
it 'has no security dashboard link' do it 'has no security dashboard link' do
expect(presenter.extra_statistics_anchors).not_to include(security_dashboard_data) expect(presenter.extra_statistics_buttons.find { |button| button[:link] == project_security_dashboard_path(project) }).to be_nil
end end
end end
end end
......
...@@ -174,6 +174,24 @@ msgstr "" ...@@ -174,6 +174,24 @@ msgstr ""
msgid "%{state} epics" msgid "%{state} epics"
msgstr "" msgstr ""
msgid "%{strong_start}%{branch_count}%{strong_end} Branch"
msgid_plural "%{strong_start}%{branch_count}%{strong_end} Branches"
msgstr[0] ""
msgstr[1] ""
msgid "%{strong_start}%{commit_count}%{strong_end} Commit"
msgid_plural "%{strong_start}%{commit_count}%{strong_end} Commits"
msgstr[0] ""
msgstr[1] ""
msgid "%{strong_start}%{human_size}%{strong_end} Files"
msgstr ""
msgid "%{strong_start}%{tag_count}%{strong_end} Tag"
msgid_plural "%{strong_start}%{tag_count}%{strong_end} Tags"
msgstr[0] ""
msgstr[1] ""
msgid "%{text} %{files}" msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files" msgid_plural "%{text} %{files} files"
msgstr[0] "" msgstr[0] ""
...@@ -402,10 +420,10 @@ msgstr "" ...@@ -402,10 +420,10 @@ msgstr ""
msgid "Add" msgid "Add"
msgstr "" msgstr ""
msgid "Add Changelog" msgid "Add CHANGELOG"
msgstr "" msgstr ""
msgid "Add Contribution guide" msgid "Add CONTRIBUTING"
msgstr "" msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition." msgid "Add Group Webhooks and GitLab Enterprise Edition."
...@@ -417,7 +435,7 @@ msgstr "" ...@@ -417,7 +435,7 @@ msgstr ""
msgid "Add Kubernetes cluster" msgid "Add Kubernetes cluster"
msgstr "" msgstr ""
msgid "Add Readme" msgid "Add README"
msgstr "" msgstr ""
msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message." msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
...@@ -1232,11 +1250,6 @@ msgstr "" ...@@ -1232,11 +1250,6 @@ msgstr ""
msgid "Branch %{branchName} was not found in this project's repository." msgid "Branch %{branchName} was not found in this project's repository."
msgstr "" msgstr ""
msgid "Branch (%{branch_count})"
msgid_plural "Branches (%{branch_count})"
msgstr[0] ""
msgstr[1] ""
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}" msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "" msgstr ""
...@@ -1402,6 +1415,9 @@ msgstr "" ...@@ -1402,6 +1415,9 @@ msgstr ""
msgid "ByAuthor|by" msgid "ByAuthor|by"
msgstr "" msgstr ""
msgid "CHANGELOG"
msgstr ""
msgid "CI / CD" msgid "CI / CD"
msgstr "" msgstr ""
...@@ -1468,6 +1484,9 @@ msgstr "" ...@@ -1468,6 +1484,9 @@ msgstr ""
msgid "CICD|instance enabled" msgid "CICD|instance enabled"
msgstr "" msgstr ""
msgid "CONTRIBUTING"
msgstr ""
msgid "Callback URL" msgid "Callback URL"
msgstr "" msgstr ""
...@@ -1519,9 +1538,6 @@ msgstr "" ...@@ -1519,9 +1538,6 @@ msgstr ""
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes." msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
msgstr "" msgstr ""
msgid "Changelog"
msgstr ""
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision." msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr "" msgstr ""
...@@ -1738,9 +1754,18 @@ msgstr "" ...@@ -1738,9 +1754,18 @@ msgstr ""
msgid "Clients" msgid "Clients"
msgstr "" msgstr ""
msgid "Clone"
msgstr ""
msgid "Clone repository" msgid "Clone repository"
msgstr "" msgstr ""
msgid "Clone with %{http_label}"
msgstr ""
msgid "Clone with SSH"
msgstr ""
msgid "Close" msgid "Close"
msgstr "" msgstr ""
...@@ -2182,6 +2207,9 @@ msgstr "" ...@@ -2182,6 +2207,9 @@ msgstr ""
msgid "Collapse sidebar" msgid "Collapse sidebar"
msgstr "" msgstr ""
msgid "Command line instructions"
msgstr ""
msgid "Comment" msgid "Comment"
msgstr "" msgstr ""
...@@ -2202,11 +2230,6 @@ msgid_plural "Commits" ...@@ -2202,11 +2230,6 @@ msgid_plural "Commits"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "Commit (%{commit_count})"
msgid_plural "Commits (%{commit_count})"
msgstr[0] ""
msgstr[1] ""
msgid "Commit Message" msgid "Commit Message"
msgstr "" msgstr ""
...@@ -2411,9 +2434,6 @@ msgstr "" ...@@ -2411,9 +2434,6 @@ msgstr ""
msgid "Contribution Charts" msgid "Contribution Charts"
msgstr "" msgstr ""
msgid "Contribution guide"
msgstr ""
msgid "Contributions for <strong>%{calendar_date}</strong>" msgid "Contributions for <strong>%{calendar_date}</strong>"
msgstr "" msgstr ""
...@@ -2453,10 +2473,10 @@ msgstr "" ...@@ -2453,10 +2473,10 @@ msgstr ""
msgid "ConvDev Index" msgid "ConvDev Index"
msgstr "" msgstr ""
msgid "Copy %{protocol} clone URL" msgid "Copy %{http_label} clone URL"
msgstr "" msgstr ""
msgid "Copy HTTPS clone URL" msgid "Copy %{protocol} clone URL"
msgstr "" msgstr ""
msgid "Copy ID to clipboard" msgid "Copy ID to clipboard"
...@@ -2525,6 +2545,9 @@ msgstr "" ...@@ -2525,6 +2545,9 @@ msgstr ""
msgid "Create a new issue" msgid "Create a new issue"
msgstr "" msgstr ""
msgid "Create a new repository"
msgstr ""
msgid "Create a personal access token on your account to pull or push via %{protocol}." msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "" msgstr ""
...@@ -3409,6 +3432,12 @@ msgstr "" ...@@ -3409,6 +3432,12 @@ msgstr ""
msgid "Everyone can contribute" msgid "Everyone can contribute"
msgstr "" msgstr ""
msgid "Existing Git repository"
msgstr ""
msgid "Existing folder"
msgstr ""
msgid "Expand" msgid "Expand"
msgstr "" msgstr ""
...@@ -3616,9 +3645,6 @@ msgstr "" ...@@ -3616,9 +3645,6 @@ msgstr ""
msgid "Files" msgid "Files"
msgstr "" msgstr ""
msgid "Files (%{human_size})"
msgstr ""
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>" msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "" msgstr ""
...@@ -4108,6 +4134,9 @@ msgstr "" ...@@ -4108,6 +4134,9 @@ msgstr ""
msgid "Git" msgid "Git"
msgstr "" msgstr ""
msgid "Git global setup"
msgstr ""
msgid "Git repository URL" msgid "Git repository URL"
msgstr "" msgstr ""
...@@ -5867,6 +5896,12 @@ msgstr "" ...@@ -5867,6 +5896,12 @@ msgstr ""
msgid "Notification events" msgid "Notification events"
msgstr "" msgstr ""
msgid "Notification setting"
msgstr ""
msgid "Notification setting - %{notification_title}"
msgstr ""
msgid "NotificationEvent|Close issue" msgid "NotificationEvent|Close issue"
msgstr "" msgstr ""
...@@ -6997,6 +7032,9 @@ msgstr "" ...@@ -6997,6 +7032,9 @@ msgstr ""
msgid "Quick actions can be used in the issues description and comment boxes." msgid "Quick actions can be used in the issues description and comment boxes."
msgstr "" msgstr ""
msgid "README"
msgstr ""
msgid "Read more" msgid "Read more"
msgstr "" msgstr ""
...@@ -7006,9 +7044,6 @@ msgstr "" ...@@ -7006,9 +7044,6 @@ msgstr ""
msgid "Read more about project permissions <strong>%{link_to_help}</strong>" msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr "" msgstr ""
msgid "Readme"
msgstr ""
msgid "Real-time features" msgid "Real-time features"
msgstr "" msgstr ""
...@@ -8266,11 +8301,6 @@ msgstr "" ...@@ -8266,11 +8301,6 @@ msgstr ""
msgid "System metrics (Kubernetes)" msgid "System metrics (Kubernetes)"
msgstr "" msgstr ""
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
msgstr[1] ""
msgid "Tags" msgid "Tags"
msgstr "" msgstr ""
......
...@@ -10,54 +10,9 @@ describe 'Projects > Show > Developer views empty project instructions' do ...@@ -10,54 +10,9 @@ describe 'Projects > Show > Developer views empty project instructions' do
sign_in(developer) sign_in(developer)
end end
context 'without an SSH key' do it 'displays "git clone" instructions' do
it 'defaults to HTTP' do
visit_project
expect_instructions_for('http')
end
it 'switches to SSH', :js do
visit_project
select_protocol('SSH')
expect_instructions_for('ssh')
end
end
context 'with an SSH key' do
before do
create(:personal_key, user: developer)
end
it 'defaults to SSH' do
visit_project
expect_instructions_for('ssh')
end
it 'switches to HTTP', :js do
visit_project
select_protocol('HTTP')
expect_instructions_for('http')
end
end
def visit_project
visit project_path(project) visit project_path(project)
end
def select_protocol(protocol)
find('#clone-dropdown').click
find(".#{protocol.downcase}-selector").click
end
def expect_instructions_for(protocol)
msg = :"#{protocol.downcase}_url_to_repo"
expect(page).to have_content("git clone #{project.send(msg)}") expect(page).to have_content("git clone")
end end
end end
...@@ -8,13 +8,18 @@ describe 'Projects > Show > User manages notifications', :js do ...@@ -8,13 +8,18 @@ describe 'Projects > Show > User manages notifications', :js do
visit project_path(project) visit project_path(project)
end end
it 'changes the notification setting' do def click_notifications_button
first('.notifications-btn').click first('.notifications-btn').click
end
it 'changes the notification setting' do
click_notifications_button
click_link 'On mention' click_link 'On mention'
page.within '#notifications-button' do wait_for_requests
expect(page).to have_content 'On mention'
end click_notifications_button
expect(find('.update-notification.is-active')).to have_content('On mention')
end end
context 'custom notification settings' do context 'custom notification settings' do
...@@ -38,7 +43,7 @@ describe 'Projects > Show > User manages notifications', :js do ...@@ -38,7 +43,7 @@ describe 'Projects > Show > User manages notifications', :js do
end end
it 'shows notification settings checkbox' do it 'shows notification settings checkbox' do
first('.notifications-btn').click click_notifications_button
page.find('a[data-notification-level="custom"]').click page.find('a[data-notification-level="custom"]').click
page.within('.custom-notifications-form') do page.within('.custom-notifications-form') do
......
...@@ -21,18 +21,6 @@ describe 'Projects > Show > Collaboration links' do ...@@ -21,18 +21,6 @@ describe 'Projects > Show > Collaboration links' do
end end
end end
# The project header
page.within('.project-home-panel') do
aggregate_failures 'dropdown links in the project home panel' do
expect(page).to have_link('New issue')
expect(page).to have_link('New merge request')
expect(page).to have_link('New snippet')
expect(page).to have_link('New file')
expect(page).to have_link('New branch')
expect(page).to have_link('New tag')
end
end
# The dropdown above the tree # The dropdown above the tree
page.within('.repo-breadcrumb') do page.within('.repo-breadcrumb') do
aggregate_failures 'dropdown links above the repo tree' do aggregate_failures 'dropdown links above the repo tree' do
...@@ -61,17 +49,6 @@ describe 'Projects > Show > Collaboration links' do ...@@ -61,17 +49,6 @@ describe 'Projects > Show > Collaboration links' do
end end
end end
page.within('.project-home-panel') do
aggregate_failures 'dropdown links' do
expect(page).not_to have_link('New issue')
expect(page).not_to have_link('New merge request')
expect(page).not_to have_link('New snippet')
expect(page).not_to have_link('New file')
expect(page).not_to have_link('New branch')
expect(page).not_to have_link('New tag')
end
end
page.within('.repo-breadcrumb') do page.within('.repo-breadcrumb') do
aggregate_failures 'dropdown links' do aggregate_failures 'dropdown links' do
expect(page).not_to have_link('New file') expect(page).not_to have_link('New file')
......
...@@ -29,7 +29,7 @@ describe 'Projects > Show > User sees Git instructions' do ...@@ -29,7 +29,7 @@ describe 'Projects > Show > User sees Git instructions' do
expect(element.text).to include(project.http_url_to_repo) expect(element.text).to include(project.http_url_to_repo)
end end
expect(page).to have_field('project_clone', with: project.http_url_to_repo) unless user_has_ssh_key expect(page).to have_field('http_project_clone', with: project.http_url_to_repo) unless user_has_ssh_key
end end
end end
...@@ -41,7 +41,7 @@ describe 'Projects > Show > User sees Git instructions' do ...@@ -41,7 +41,7 @@ describe 'Projects > Show > User sees Git instructions' do
expect(page).to have_content(project.title) expect(page).to have_content(project.title)
end end
expect(page).to have_field('project_clone', with: project.http_url_to_repo) unless user_has_ssh_key expect(page).to have_field('http_project_clone', with: project.http_url_to_repo) unless user_has_ssh_key
end end
end end
......
...@@ -13,7 +13,7 @@ describe 'Maintainer views tags' do ...@@ -13,7 +13,7 @@ describe 'Maintainer views tags' do
before do before do
visit project_path(project) visit project_path(project)
click_on 'Add Readme' click_on 'Add README'
fill_in :commit_message, with: 'Add a README file', visible: true fill_in :commit_message, with: 'Add a README file', visible: true
click_button 'Commit changes' click_button 'Commit changes'
visit project_tags_path(project) visit project_tags_path(project)
......
This diff is collapsed.
...@@ -23,7 +23,7 @@ describe 'projects/_home_panel' do ...@@ -23,7 +23,7 @@ describe 'projects/_home_panel' do
it 'makes it possible to set notification level' do it 'makes it possible to set notification level' do
render render
expect(view).to render_template('shared/notifications/_button') expect(view).to render_template('projects/buttons/_notifications')
expect(rendered).to have_selector('.notification-dropdown') expect(rendered).to have_selector('.notification-dropdown')
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment