Commit 056f6dd0 authored by Dennis Tang's avatar Dennis Tang

Refresh group overview to match project overview

- Avatar, group name, and group description now left-aligned
- Notification setting and "New project" CTA right-aligned
  with group avatar and name
- Leave group / request access now a link next to the 'Group'
  label below the group name
- Notification setting label removed in favor of icons
  - Tooltip added to indicate notification setting
- Search option moved inside table header next to "Sort by"
parent ce171674
...@@ -278,8 +278,8 @@ $performance-bar-height: 35px; ...@@ -278,8 +278,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: 64px; $home-panel-title-row-height: 64px;
$project-avatar-mobile-size: 24px; $home-panel-avatar-mobile-size: 24px;
$gl-line-height: 16px; $gl-line-height: 16px;
$gl-line-height-24: 24px; $gl-line-height-24: 24px;
$gl-line-height-14: 14px; $gl-line-height-14: 14px;
......
...@@ -29,9 +29,7 @@ ...@@ -29,9 +29,7 @@
} }
} }
.group-nav-container .group-search,
.group-nav-container .nav-controls { .group-nav-container .nav-controls {
display: flex;
align-items: flex-start; align-items: flex-start;
padding: $gl-padding-top 0 0; padding: $gl-padding-top 0 0;
...@@ -44,6 +42,52 @@ ...@@ -44,6 +42,52 @@
margin-top: 0; margin-top: 0;
} }
@include media-breakpoint-down(sm) {
.dropdown,
.dropdown .dropdown-toggle,
.btn-success {
display: block;
}
.group-filter-form,
.dropdown {
margin-bottom: 10px;
margin-right: 0;
}
&,
.group-filter-form,
.group-filter-form-field,
.dropdown,
.dropdown .dropdown-toggle,
.btn-success {
width: 100%;
}
.dropdown .dropdown-toggle .fa-chevron-down {
position: absolute;
top: 11px;
right: 8px;
}
}
}
.home-panel-buttons {
.home-panel-action-button {
vertical-align: top;
}
.notification-dropdown {
.dropdown-menu {
@extend .dropdown-menu-right;
}
.icon {
fill: $gl-text-color-secondary;
}
}
.new-project-subgroup { .new-project-subgroup {
.dropdown-primary { .dropdown-primary {
min-width: 115px; min-width: 115px;
...@@ -99,61 +143,29 @@ ...@@ -99,61 +143,29 @@
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
} }
} }
}
}
@include media-breakpoint-down(sm) {
&,
.dropdown,
.dropdown .dropdown-toggle,
.btn-success {
display: block;
}
.group-filter-form, @include media-breakpoint-down(sm) {
.dropdown { display: flex;
margin-bottom: 10px; align-items: flex-start;
margin-right: 0;
}
.group-filter-form,
.dropdown .dropdown-toggle,
.btn-success {
width: 100%;
}
.dropdown .dropdown-toggle .fa-chevron-down {
position: absolute;
top: 11px;
right: 8px;
}
.new-project-subgroup {
display: flex;
align-items: flex-start;
.dropdown-primary { .dropdown-primary {
flex: 1; flex: 1;
} }
.dropdown-toggle { .dropdown-toggle {
width: auto; width: auto;
} }
.dropdown-menu { .dropdown-menu {
width: 100%; width: 100%;
max-width: inherit; max-width: inherit;
min-width: inherit; min-width: inherit;
}
} }
} }
} }
} }
.group-nav-container .group-search {
padding: $gl-padding 0;
border-bottom: 1px solid $border-color;
}
.groups-listing { .groups-listing {
.group-list-tree .group-row:first-child { .group-list-tree .group-row:first-child {
border-top: 0; border-top: 0;
......
...@@ -140,73 +140,19 @@ ...@@ -140,73 +140,19 @@
} }
} }
.project-home-panel, .group-home-panel,
.group-home-panel {
padding-top: 24px;
padding-bottom: 24px;
.group-avatar {
float: none;
margin: 0 auto;
&.identicon {
border-radius: 50%;
}
}
.group-title {
margin-top: 10px;
margin-bottom: 10px;
font-size: 24px;
font-weight: $gl-font-weight-normal;
line-height: 1;
word-wrap: break-word;
.fa {
margin-left: 2px;
font-size: 12px;
vertical-align: middle;
}
}
.group-home-desc {
margin-left: auto;
margin-right: auto;
margin-bottom: 0;
max-width: 700px;
> p {
margin-bottom: 0;
}
}
.notifications-btn {
.fa-bell,
.fa-spinner {
margin-right: 6px;
}
.fa-angle-down {
margin-left: 6px;
}
}
}
.project-home-panel { .project-home-panel {
padding-top: $gl-padding; padding-top: $gl-padding;
padding-bottom: $gl-padding; padding-bottom: $gl-padding;
.project-avatar { .home-panel-avatar {
width: $project-title-row-height; width: $home-panel-title-row-height;
height: $project-title-row-height; height: $home-panel-title-row-height;
flex-shrink: 0; flex-shrink: 0;
flex-basis: $project-title-row-height; flex-basis: $home-panel-title-row-height;
margin: 0 $gl-padding 0 0;
} }
.project-title { .home-panel-title {
margin-top: 8px;
margin-bottom: 5px;
font-size: 20px; font-size: 20px;
line-height: $gl-line-height-24; line-height: $gl-line-height-24;
font-weight: bold; font-weight: bold;
...@@ -215,11 +161,7 @@ ...@@ -215,11 +161,7 @@
font-size: $gl-font-size-large; font-size: $gl-font-size-large;
} }
.project-visibility { .home-panel-topic-list {
color: $gl-text-color-secondary;
}
.project-topic-list {
font-size: $gl-font-size; font-size: $gl-font-size;
font-weight: $gl-font-weight-normal; font-weight: $gl-font-weight-normal;
...@@ -231,12 +173,12 @@ ...@@ -231,12 +173,12 @@
} }
} }
.project-title-row { .home-panel-title-row {
@include media-breakpoint-down(sm) { @include media-breakpoint-down(sm) {
.project-avatar { .home-panel-avatar {
width: $project-avatar-mobile-size; width: $home-panel-avatar-mobile-size;
height: $project-avatar-mobile-size; height: $home-panel-avatar-mobile-size;
flex-basis: $project-avatar-mobile-size; flex-basis: $home-panel-avatar-mobile-size;
.avatar { .avatar {
font-size: 20px; font-size: 20px;
...@@ -244,28 +186,26 @@ ...@@ -244,28 +186,26 @@
} }
} }
.project-title { .home-panel-title {
margin-top: 4px; margin-top: 4px;
margin-bottom: 2px; margin-bottom: 2px;
font-size: $gl-font-size; font-size: $gl-font-size;
line-height: $gl-font-size-large; line-height: $gl-font-size-large;
} }
.project-topic-list, .home-panel-topic-list,
.project-metadata { .home-panel-metadata {
font-size: $gl-font-size-small; font-size: $gl-font-size-small;
} }
} }
} }
.project-metadata { .home-panel-metadata {
font-weight: normal; font-weight: normal;
font-size: 14px; font-size: 14px;
line-height: $gl-btn-line-height; line-height: $gl-btn-line-height;
color: $gl-text-color-secondary;
.project-license { .home-panel-license {
.btn { .btn {
line-height: 0; line-height: 0;
border-width: 0; border-width: 0;
...@@ -273,13 +213,13 @@ ...@@ -273,13 +213,13 @@
} }
.access-request-link, .access-request-link,
.project-topic-list { .home-panel-topic-list {
padding-left: $gl-padding-8; padding-left: $gl-padding-8;
border-left: 1px solid $gl-text-color-secondary; border-left: 1px solid $gl-text-color-secondary;
} }
} }
.project-description { .home-panel-description {
@include media-breakpoint-up(md) { @include media-breakpoint-up(md) {
font-size: $gl-font-size-large; font-size: $gl-font-size-large;
} }
...@@ -292,12 +232,11 @@ ...@@ -292,12 +232,11 @@
} }
} }
.nav > .project-repo-buttons { .nav > .project-buttons {
margin-top: 0; margin-top: 0;
} }
.project-repo-buttons, .project-repo-buttons {
.group-buttons {
.btn { .btn {
&:last-child { &:last-child {
margin-left: 0; margin-left: 0;
...@@ -318,8 +257,30 @@ ...@@ -318,8 +257,30 @@
margin-left: 0; margin-left: 0;
} }
} }
.notifications-icon {
top: 1px;
margin-right: 0;
}
} }
.icon {
top: 0;
}
.count-badge,
.btn-xs {
height: 24px;
}
.dropdown-toggle,
.clone-dropdown-btn {
.fa {
color: unset;
}
}
.home-panel-action-button,
.project-action-button { .project-action-button {
margin: $gl-padding $gl-padding-8 0 0; margin: $gl-padding $gl-padding-8 0 0;
vertical-align: top; vertical-align: top;
...@@ -385,31 +346,6 @@ ...@@ -385,31 +346,6 @@
} }
} }
.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;
...@@ -772,9 +708,6 @@ ...@@ -772,9 +708,6 @@
.project-stats, .project-stats,
.project-buttons { .project-buttons {
font-size: 0;
text-align: center;
.scrolling-tabs-container { .scrolling-tabs-container {
.scrolling-tabs { .scrolling-tabs {
margin-top: $gl-padding-8; margin-top: $gl-padding-8;
......
...@@ -17,7 +17,8 @@ class NotificationSettingsController < ApplicationController ...@@ -17,7 +17,8 @@ class NotificationSettingsController < ApplicationController
@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? if params[:hide_label].present?
render_response("projects/buttons/_notifications") btn_class = params[:project_id].present? ? 'btn-xs' : ''
render_response("shared/notifications/_new_button", btn_class)
else else
render_response render_response
end end
...@@ -41,9 +42,9 @@ class NotificationSettingsController < ApplicationController ...@@ -41,9 +42,9 @@ class NotificationSettingsController < ApplicationController
can?(current_user, ability_name, resource) can?(current_user, ability_name, resource)
end end
def render_response(response_template = "shared/notifications/_button") def render_response(response_template = "shared/notifications/_button", btn_class = nil)
render json: { render json: {
html: view_to_html_string(response_template, notification_setting: @notification_setting), html: view_to_html_string(response_template, notification_setting: @notification_setting, btn_class: btn_class),
saved: @saved saved: @saved
} }
end end
......
.group-home-panel.text-center.border-bottom - can_create_subgroups = can?(current_user, :create_subgroup, @group)
%div{ class: container_class }
.avatar-container.s70.group-avatar
= group_icon(@group, class: "avatar s70 avatar-tile")
%h1.group-title
= @group.name
%span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, fw: false)
- if @group.description.present? .group-home-panel
.group-home-desc .row.mb-3
= markdown_field(@group, :description) .home-panel-title-row.col-md-12.col-lg-6.d-flex
.avatar-container.home-panel-avatar.append-right-default.float-none
= group_icon(@group, class: 'avatar avatar-tile s64', width: 64, height: 64)
.d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline
%h1.home-panel-title.prepend-top-8.append-bottom-5
= @group.name
%span.visibility-icon.text-secondary.prepend-left-4.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
= visibility_level_icon(@group.visibility_level, fw: false, options: {class: 'icon'})
.home-panel-metadata.d-flex.align-items-center.text-secondary
%span
= _("Group")
- if current_user
%span.access-request-links.prepend-left-8
= render 'shared/members/access_request_links', source: @group
- if current_user .home-panel-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
.group-buttons.d-none.d-sm-block - if current_user
= render 'shared/members/access_request_buttons', source: @group .group-buttons
= render 'shared/notifications/button', notification_setting: @notification_setting = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn'
- if can? current_user, :create_projects, @group
- new_project_label = _("New project")
- new_subgroup_label = _("New subgroup")
- if can_create_subgroups
.btn-group.new-project-subgroup.droplab-dropdown.home-panel-action-button.prepend-top-default.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
%input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } }
%button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
= sprite_icon("arrow-down", css_class: "icon")
%ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } }
%li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } }
.menu-item
.icon-container
= icon("check", class: "list-item-checkmark")
.description
%strong= new_project_label
%span= s_("GroupsTree|Create a project in this group.")
%li.divider.droplap-item-ignore
%li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
.menu-item
.icon-container
= icon("check", class: "list-item-checkmark")
.description
%strong= new_subgroup_label
%span= s_("GroupsTree|Create a subgroup in this group.")
- else
= link_to new_project_label, new_project_path(namespace_id: @group.id), class: "btn btn-success"
- if @group.description.present?
.group-home-desc.mt-1
.home-panel-description
.home-panel-description-markdown.read-more-container
= markdown_field(@group, :description)
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more")
- @no_container = true - @no_container = true
- breadcrumb_title _("Details") - breadcrumb_title _("Details")
- can_create_subgroups = can?(current_user, :create_subgroup, @group) - @content_class = "limit-container-width" unless fluid_layout
= content_for :meta_tags do = content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity") = auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
= render 'groups/home_panel' %div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
= render 'groups/home_panel'
.groups-listing{ class: container_class, data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
.top-area.group-nav-container .groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
.group-search .top-area.group-nav-container
= render "shared/groups/search_form" .scrolling-tabs-container.inner-page-scroll-tabs
- if can? current_user, :create_projects, @group .fade-left= icon('angle-left')
- new_project_label = _("New project") .fade-right= icon('angle-right')
- new_subgroup_label = _("New subgroup") %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
- if can_create_subgroups %li.js-subgroups_and_projects-tab
.btn-group.new-project-subgroup.droplab-dropdown.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } } = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
%input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } } = _("Subgroups and projects")
%button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } } %li.js-shared-tab
= icon("caret-down", class: "dropdown-btn-icon") = link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
%ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } } = _("Shared projects")
%li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } } %li.js-archived-tab
.menu-item = link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
.icon-container = _("Archived projects")
= icon("check", class: "list-item-checkmark")
.description .nav-controls.d-block.d-md-flex
%strong= new_project_label .group-search
%span= s_("GroupsTree|Create a project in this group.") = render "shared/groups/search_form"
%li.divider.droplap-item-ignore
%li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } } = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
.menu-item
.icon-container .tab-content
= icon("check", class: "list-item-checkmark") #subgroups_and_projects.tab-pane
.description = render "subgroups_and_projects", group: @group
%strong= new_subgroup_label
%span= s_("GroupsTree|Create a subgroup in this group.") #shared.tab-pane
- else = render "shared_projects", group: @group
= link_to new_project_label, new_project_path(namespace_id: @group.id), class: "btn btn-success"
#archived.tab-pane
.scrolling-tabs-container.inner-page-scroll-tabs = render "archived_projects", group: @group
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
%ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
%li.js-subgroups_and_projects-tab
= link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
= _("Subgroups and projects")
%li.js-shared-tab
= link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
= _("Shared projects")
%li.js-archived-tab
= link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
= _("Archived projects")
.nav-controls
= render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
.tab-content
#subgroups_and_projects.tab-pane
= render "subgroups_and_projects", group: @group
#shared.tab-pane
= render "shared_projects", group: @group
#archived.tab-pane
= render "archived_projects", group: @group
- empty_repo = @project.empty_repo? - empty_repo = @project.empty_repo?
- show_auto_devops_callout = show_auto_devops_callout?(@project) - 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) }
.project-header.row.append-bottom-8 .row.append-bottom-8
.project-title-row.col-md-12.col-lg-6.d-flex .home-panel-title-row.col-md-12.col-lg-6.d-flex
.avatar-container.project-avatar.float-none .avatar-container.home-panel-avatar.append-right-default.float-none
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64) = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64)
.d-flex.flex-column.flex-wrap.align-items-baseline .d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline .d-inline-flex.align-items-baseline
%h1.project-title.qa-project-name %h1.home-panel-title.prepend-top-8.append-bottom-5.qa-project-name
= @project.name = @project.name
%span.project-visibility.prepend-left-8.d-inline-flex.align-items-baseline.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) } %span.visibility-icon.text-secondary.prepend-left-4.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'})
.project-metadata.d-flex.align-items-center .home-panel-metadata.d-flex.align-items-center.text-secondary
- if can?(current_user, :read_project, @project) - if can?(current_user, :read_project, @project)
%span.text-secondary %span.text-secondary
= s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id } = s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
%span.access-request-links.prepend-left-8 %span.access-request-links.prepend-left-8
= render 'shared/members/access_request_links', source: @project = render 'shared/members/access_request_links', source: @project
- if @project.tag_list.present? - if @project.tag_list.present?
%span.project-topic-list.d-inline-flex.prepend-left-8.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_topics? ? @project.tag_list.join(', ') : nil } %span.home-panel-topic-list.d-inline-flex.prepend-left-8.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_topics? ? @project.tag_list.join(', ') : nil }
= sprite_icon('tag', size: 16, css_class: 'icon append-right-4') = sprite_icon('tag', size: 16, css_class: 'icon append-right-4')
= @project.topics_to_show = @project.topics_to_show
- if @project.has_extra_topics? - if @project.has_extra_topics?
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
.project-repo-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end .project-repo-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
- if current_user - if current_user
.d-inline-flex .d-inline-flex
= render 'projects/buttons/notifications', notification_setting: @notification_setting, btn_class: 'btn-xs' = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs'
.count-buttons.d-inline-flex .count-buttons.d-inline-flex
= render 'projects/buttons/star' = render 'projects/buttons/star'
...@@ -44,13 +44,13 @@ ...@@ -44,13 +44,13 @@
- if can?(current_user, :download_code, @project) - if can?(current_user, :download_code, @project)
%nav.project-stats %nav.project-stats
.nav-links.quick-links.mt-3 .nav-links.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_anchors(show_auto_devops_callout: show_auto_devops_callout)
.project-home-desc.mt-1 .home-panel-home-desc.mt-1
- if @project.description.present? - if @project.description.present?
.project-description .home-panel-description
.project-description-markdown.read-more-container .home-panel-description-markdown.read-more-container
= markdown_field(@project, :description) = markdown_field(@project, :description)
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" } %button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more") = _("Read more")
......
- 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
.project-action-button.inline
- 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: 'btn'
- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord
.project-action-button.inline
= link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
method: :delete,
data: { confirm: remove_member_message(requester) },
class: 'btn'
- elsif source.request_access_enabled && can?(current_user, :request_access, source)
.project-action-button.inline
= link_to _('Request Access'), polymorphic_path([:request_access, source, :members]),
method: :post,
class: 'btn'
- btn_class = local_assigns.fetch(:btn_class, nil) - 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.home-panel-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|
= hidden_setting_source_input(notification_setting) = hidden_setting_source_input(notification_setting)
= f.hidden_field :level, class: "notification_setting_level" = f.hidden_field :level, class: "notification_setting_level"
......
- btn_class = local_assigns.fetch(:btn_class, "btn-xs") - 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.home-panel-action-button.prepend-top-default.append-right-8.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f| = form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f|
= hidden_setting_source_input(notification_setting) = hidden_setting_source_input(notification_setting)
= hidden_field_tag "hide_label", true = hidden_field_tag "hide_label", true
...@@ -9,14 +9,14 @@ ...@@ -9,14 +9,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 - %{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' } } %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", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
= sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon") = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
%span.js-notification-loading.fa.hidden %span.js-notification-loading.fa.hidden
%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" } }
= sprite_icon("arrow-down", css_class: "icon") = sprite_icon("arrow-down", css_class: "icon")
.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 - #{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" } } %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", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon") = sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
%span.js-notification-loading.fa.hidden %span.js-notification-loading.fa.hidden
= sprite_icon("arrow-down", css_class: "icon") = sprite_icon("arrow-down", css_class: "icon")
......
---
title: Refresh group overview to match project overview
merge_request: 23866
author:
type: changed
...@@ -6,7 +6,7 @@ module QA ...@@ -6,7 +6,7 @@ module QA
class Show < Page::Base class Show < Page::Base
include Page::Component::GroupsFilter include Page::Component::GroupsFilter
view 'app/views/groups/show.html.haml' do view 'app/views/groups/_home_panel.html.haml' do
element :new_project_or_subgroup_dropdown element :new_project_or_subgroup_dropdown
element :new_project_or_subgroup_dropdown_toggle element :new_project_or_subgroup_dropdown_toggle
element :new_project_option element :new_project_option
......
...@@ -18,14 +18,14 @@ describe 'Edit group settings' do ...@@ -18,14 +18,14 @@ describe 'Edit group settings' do
update_path(new_group_path) update_path(new_group_path)
visit new_group_full_path visit new_group_full_path
expect(current_path).to eq(new_group_full_path) expect(current_path).to eq(new_group_full_path)
expect(find('h1.group-title')).to have_content(group.name) expect(find('h1.home-panel-title')).to have_content(group.name)
end end
it 'the old group path redirects to the new path' do it 'the old group path redirects to the new path' do
update_path(new_group_path) update_path(new_group_path)
visit old_group_full_path visit old_group_full_path
expect(current_path).to eq(new_group_full_path) expect(current_path).to eq(new_group_full_path)
expect(find('h1.group-title')).to have_content(group.name) expect(find('h1.home-panel-title')).to have_content(group.name)
end end
context 'with a subgroup' do context 'with a subgroup' do
...@@ -37,14 +37,14 @@ describe 'Edit group settings' do ...@@ -37,14 +37,14 @@ describe 'Edit group settings' do
update_path(new_group_path) update_path(new_group_path)
visit new_subgroup_full_path visit new_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path) expect(current_path).to eq(new_subgroup_full_path)
expect(find('h1.group-title')).to have_content(subgroup.name) expect(find('h1.home-panel-title')).to have_content(subgroup.name)
end end
it 'the old subgroup path redirects to the new path' do it 'the old subgroup path redirects to the new path' do
update_path(new_group_path) update_path(new_group_path)
visit old_subgroup_full_path visit old_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path) expect(current_path).to eq(new_subgroup_full_path)
expect(find('h1.group-title')).to have_content(subgroup.name) expect(find('h1.home-panel-title')).to have_content(subgroup.name)
end end
end end
......
...@@ -201,7 +201,7 @@ describe 'Group' do ...@@ -201,7 +201,7 @@ describe 'Group' do
visit path visit path
expect(page).to have_css('.group-home-desc > p > strong') expect(page).to have_css('.home-panel-description-markdown > p > strong')
end end
it 'passes through html-pipeline' do it 'passes through html-pipeline' do
...@@ -209,7 +209,7 @@ describe 'Group' do ...@@ -209,7 +209,7 @@ describe 'Group' do
visit path visit path
expect(page).to have_css('.group-home-desc > p > gl-emoji') expect(page).to have_css('.home-panel-description-markdown > p > gl-emoji')
end end
it 'sanitizes unwanted tags' do it 'sanitizes unwanted tags' do
...@@ -217,7 +217,7 @@ describe 'Group' do ...@@ -217,7 +217,7 @@ describe 'Group' do
visit path visit path
expect(page).not_to have_css('.group-home-desc h1') expect(page).not_to have_css('.home-panel-description-markdown h1')
end end
it 'permits `rel` attribute on links' do it 'permits `rel` attribute on links' do
...@@ -225,7 +225,7 @@ describe 'Group' do ...@@ -225,7 +225,7 @@ describe 'Group' do
visit path visit path
expect(page).to have_css('.group-home-desc a[rel]') expect(page).to have_css('.home-panel-description-markdown a[rel]')
end end
end end
......
...@@ -55,30 +55,30 @@ describe 'Project' do ...@@ -55,30 +55,30 @@ describe 'Project' do
it 'parses Markdown' do it 'parses Markdown' do
project.update_attribute(:description, 'This is **my** project') project.update_attribute(:description, 'This is **my** project')
visit path visit path
expect(page).to have_css('.project-description > .project-description-markdown > p > strong') expect(page).to have_css('.home-panel-description > .home-panel-description-markdown > p > strong')
end end
it 'passes through html-pipeline' do it 'passes through html-pipeline' do
project.update_attribute(:description, 'This project is the :poop:') project.update_attribute(:description, 'This project is the :poop:')
visit path visit path
expect(page).to have_css('.project-description > .project-description-markdown > p > gl-emoji') expect(page).to have_css('.home-panel-description > .home-panel-description-markdown > p > gl-emoji')
end end
it 'sanitizes unwanted tags' do it 'sanitizes unwanted tags' do
project.update_attribute(:description, "```\ncode\n```") project.update_attribute(:description, "```\ncode\n```")
visit path visit path
expect(page).not_to have_css('.project-description code') expect(page).not_to have_css('.home-panel-description code')
end end
it 'permits `rel` attribute on links' do it 'permits `rel` attribute on links' do
project.update_attribute(:description, 'https://google.com/') project.update_attribute(:description, 'https://google.com/')
visit path visit path
expect(page).to have_css('.project-description a[rel]') expect(page).to have_css('.home-panel-description a[rel]')
end end
context 'read more', :js do context 'read more', :js do
let(:read_more_selector) { '.read-more-container' } let(:read_more_selector) { '.read-more-container' }
let(:read_more_trigger_selector) { '.project-home-desc .js-read-more-trigger' } let(:read_more_trigger_selector) { '.home-panel-home-desc .js-read-more-trigger' }
it 'does not display "read more" link on desktop breakpoint' do it 'does not display "read more" link on desktop breakpoint' do
project.update_attribute(:description, 'This is **my** project') project.update_attribute(:description, 'This is **my** project')
...@@ -94,7 +94,7 @@ describe 'Project' do ...@@ -94,7 +94,7 @@ describe 'Project' do
find(read_more_trigger_selector).click find(read_more_trigger_selector).click
expect(page).to have_css('.project-description .is-expanded') expect(page).to have_css('.home-panel-description .is-expanded')
end end
end end
end end
...@@ -111,14 +111,14 @@ describe 'Project' do ...@@ -111,14 +111,14 @@ describe 'Project' do
it 'shows project topics' do it 'shows project topics' do
project.update_attribute(:tag_list, 'topic1') project.update_attribute(:tag_list, 'topic1')
visit path visit path
expect(page).to have_css('.project-topic-list') expect(page).to have_css('.home-panel-topic-list')
expect(page).to have_content('topic1') expect(page).to have_content('topic1')
end end
it 'shows up to 3 project tags' do it 'shows up to 3 project tags' do
project.update_attribute(:tag_list, 'topic1, topic2, topic3, topic4') project.update_attribute(:tag_list, 'topic1, topic2, topic3, topic4')
visit path visit path
expect(page).to have_css('.project-topic-list') expect(page).to have_css('.home-panel-topic-list')
expect(page).to have_content('topic1, topic2, topic3 + 1 more') expect(page).to have_content('topic1, topic2, topic3 + 1 more')
end end
end end
......
...@@ -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('projects/buttons/_notifications') expect(view).to render_template('shared/notifications/_new_button')
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