diff --git a/app/components/users/avatar_component.rb b/app/components/users/avatar_component.rb index 2bd45da1c8b1..0d3b376ab3eb 100644 --- a/app/components/users/avatar_component.rb +++ b/app/components/users/avatar_component.rb @@ -32,7 +32,7 @@ class AvatarComponent < ApplicationComponent include AvatarHelper include OpPrimer::ComponentHelpers - def initialize(user:, show_name: true, link: true, size: 'default', classes: '', title: nil) + def initialize(user:, show_name: true, link: true, size: 'default', classes: '', title: nil, name_classes: '') super @user = user @@ -41,6 +41,7 @@ def initialize(user:, show_name: true, link: true, size: 'default', classes: '', @size = size @title = title @classes = classes + @name_classes = name_classes end def render? @@ -54,7 +55,8 @@ def call link: @link, hide_name: !@show_name, title: @title, - class: @classes + class: @classes, + name_classes: @name_classes ) end end diff --git a/frontend/src/app/shared/components/principal/principal-renderer.service.ts b/frontend/src/app/shared/components/principal/principal-renderer.service.ts index 3869d8f48570..3905b53562e2 100644 --- a/frontend/src/app/shared/components/principal/principal-renderer.service.ts +++ b/frontend/src/app/shared/components/principal/principal-renderer.service.ts @@ -21,6 +21,7 @@ export interface AvatarOptions { export interface NameOptions { hide:boolean; link:boolean; + classes?:string; } @Injectable({ providedIn: 'root' }) @@ -81,7 +82,7 @@ export class PrincipalRendererService { } if (!name.hide) { - const el = this.renderName(principal, type, name.link, title || principal.name); + const el = this.renderName(principal, type, name.link, title || principal.name, name.classes); container.appendChild(el); } } @@ -148,6 +149,7 @@ export class PrincipalRendererService { type:PrincipalType, asLink = true, title = '', + classes = '', ) { if (asLink) { const link = document.createElement('a'); @@ -164,6 +166,9 @@ export class PrincipalRendererService { span.textContent = principal.name; span.classList.add('op-principal--name'); span.title = title; + classes !== '' && classes.split(' ').forEach((cls) => { + span.classList.add(cls); + }); return span; } diff --git a/frontend/src/app/shared/components/principal/principal.component.ts b/frontend/src/app/shared/components/principal/principal.component.ts index e2ee49b5df33..99cee1547a61 100644 --- a/frontend/src/app/shared/components/principal/principal.component.ts +++ b/frontend/src/app/shared/components/principal/principal.component.ts @@ -70,6 +70,8 @@ export class OpPrincipalComponent implements OnInit { @Input() hideName = false; + @Input() nameClasses? = ''; + @Input() link = true; @Input() size:AvatarSize = 'default'; @@ -97,6 +99,7 @@ export class OpPrincipalComponent implements OnInit { { hide: this.hideName, link: this.link, + classes: this.nameClasses, }, { hide: this.hideAvatar, diff --git a/frontend/src/global_styles/layout/_base_mobile.sass b/frontend/src/global_styles/layout/_base_mobile.sass index 8ce9b5d0b8c4..0976f75eebc0 100644 --- a/frontend/src/global_styles/layout/_base_mobile.sass +++ b/frontend/src/global_styles/layout/_base_mobile.sass @@ -83,3 +83,8 @@ @media screen and (max-width: $breakpoint-md) .hidden-for-tablet display: none !important + +@media screen and (max-width: $breakpoint-lg) and (min-width: $breakpoint-sm) + .hidden-for-tablet-and-small-laptops + display: none !important + diff --git a/modules/avatars/app/helpers/avatar_helper.rb b/modules/avatars/app/helpers/avatar_helper.rb index 1e35039197ab..1bcbc12a973d 100644 --- a/modules/avatars/app/helpers/avatar_helper.rb +++ b/modules/avatars/app/helpers/avatar_helper.rb @@ -45,8 +45,8 @@ module AvatarHelper # Returns the avatar image tag for the given +user+ if avatars are enabled # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe ') - def avatar(principal, size: 'default', hide_name: true, **options) - build_principal_avatar_tag principal, size:, hide_name:, **options + def avatar(principal, size: 'default', hide_name: true, name_classes: '', **options) + build_principal_avatar_tag principal, size:, hide_name:, name_classes:, **options rescue StandardError => e Rails.logger.error "Failed to create avatar for #{principal}: #{e}" ''.html_safe @@ -106,6 +106,7 @@ def build_principal_avatar_tag(user, **options) link: tag_options[:link], size: tag_options[:size], hideName: tag_options[:hide_name], + nameClasses: tag_options[:name_classes], title: tag_options.fetch(:title, '') } end diff --git a/modules/avatars/spec/helpers/avatar_helper_spec.rb b/modules/avatars/spec/helpers/avatar_helper_spec.rb index db43d485850b..1a09bdfb6ffa 100644 --- a/modules/avatars/spec/helpers/avatar_helper_spec.rb +++ b/modules/avatars/spec/helpers/avatar_helper_spec.rb @@ -35,6 +35,7 @@ def expected_user_avatar_tag(user) inputs: { principal:, hideName: true, + nameClasses: '', link: nil, title: user.name, size: 'default' diff --git a/modules/storages/app/components/storages/admin/storage_list_component.html.erb b/modules/storages/app/components/storages/admin/storage_list_component.html.erb index 4dd4f850b3c7..53d43573d2d0 100644 --- a/modules/storages/app/components/storages/admin/storage_list_component.html.erb +++ b/modules/storages/app/components/storages/admin/storage_list_component.html.erb @@ -3,7 +3,7 @@ render(Primer::Beta::BorderBox.new) do |component| component.with_header(color: :subtle) do grid_layout('op-storage-list--header', tag: :div, align_items: :center) do |grid| - grid.with_area(:name, tag: :div) do + grid.with_area(:name, tag: :div, mr: 3) do render(Primer::Beta::Text.new(font_weight: :semibold)) { I18n.t('storages.label_name') } end @@ -24,7 +24,7 @@ storages.map do |storage| component.with_row(scheme: :default, id: storage_row_css_id(storage)) do grid_layout('op-storage-list--row', tag: :div, align_items: :center) do |grid| - grid.with_area(:name, tag: :div, mr: 3) do + grid.with_area(:name, tag: :div, mr: 3, classes: 'ellipsis') do concat(render(Primer::Beta::Link.new(href: edit_admin_settings_storage_path(storage), scheme: :primary, mr: 1, data: { 'test-selector': 'storage-name' })) { storage.name }) unless storage.configured? @@ -32,19 +32,19 @@ end end - grid.with_area(:host, tag: :div, color: :subtle, data: { 'test-selector': 'storage-host' }) do + grid.with_area(:host, tag: :div, mr: 3, color: :subtle, data: { 'test-selector': 'storage-host' }, classes: 'ellipsis') do render(Primer::Beta::Truncate.new(font_weight: :light)) { storage.host } end - grid.with_area(:user, tag: :div, color: :subtle, mr: 3, font_weight: :light, data: { 'test-selector': 'storage-creator' }) do - render(Users::AvatarComponent.new(user: storage.creator, size: :mini, link: false, show_name: true)) + grid.with_area(:user, tag: :div, color: :subtle, mr: 3, font_weight: :light, data: { 'test-selector': 'storage-creator' }, classes: 'ellipsis') do + render(Users::AvatarComponent.new(user: storage.creator, size: :mini, link: false, show_name: true, name_classes: 'hidden-for-tablet-and-small-laptops')) end grid.with_area(:provider, tag: :div, color: :subtle, mr: 3, hide: :sm, data: { 'test-selector': 'storage-provider' }) do render(Primer::Beta::Truncate.new(font_weight: :light)) { I18n.t("storages.provider_types.#{storage.short_provider_type}.name") } end - grid.with_area(:time, tag: :div, color: :subtle, mr: 3) do + grid.with_area(:time, tag: :div, color: :subtle) do render(Primer::Beta::Text.new(font_weight: :light)) { I18n.t('activity.item.created_on', datetime: helpers.format_time(storage.created_at)).capitalize } end end diff --git a/modules/storages/app/components/storages/admin/storage_list_component.sass b/modules/storages/app/components/storages/admin/storage_list_component.sass index 968330dbf931..54c623352d54 100644 --- a/modules/storages/app/components/storages/admin/storage_list_component.sass +++ b/modules/storages/app/components/storages/admin/storage_list_component.sass @@ -1,10 +1,15 @@ .op-storage-list--header, .op-storage-list--row display: grid - grid-template-columns: 1fr 180px 160px 240px - grid-template-areas: "name user provider time" "host user provider time" + grid-template-columns: 1fr 160px 180px 220px + grid-template-areas: "name provider user time" "host provider user time" -@media screen and (max-width: $breakpoint-md) +@media screen and (max-width: $breakpoint-lg) + .op-storage-list--header, + .op-storage-list--row + grid-template-columns: 1fr 160px 60px 140px + +@media screen and (max-width: $breakpoint-sm) .op-storage-list--row grid-template-columns: 1fr grid-template-areas: "name" "host" "user" "time"