Commit a999d8d4 authored by Tom Quirk's avatar Tom Quirk Committed by Kushal Pandya

Create UserAccessRoleBadge component

Adds component that wraps GlBadge, but applies
some custom styles.

We then use this component whereever the
.user-access-role class is used in Vue components.
parent aa8384f1
<script>
/* eslint-disable vue/no-v-html */
import { GlLoadingIcon, GlBadge, GlTooltipDirective } from '@gitlab/ui';
import { visitUrl } from '../../lib/utils/url_utility';
import identicon from '../../vue_shared/components/identicon.vue';
import {
GlLoadingIcon,
GlBadge,
GlIcon,
GlTooltipDirective,
GlSafeHtmlDirective,
} from '@gitlab/ui';
import { visitUrl } from '~/lib/utils/url_utility';
import identicon from '~/vue_shared/components/identicon.vue';
import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '../constants';
import eventHub from '../event_hub';
import itemActions from './item_actions.vue';
import itemCaret from './item_caret.vue';
import itemStats from './item_stats.vue';
import itemStatsValue from './item_stats_value.vue';
import itemTypeIcon from './item_type_icon.vue';
export default {
directives: {
GlTooltip: GlTooltipDirective,
SafeHtml: GlSafeHtmlDirective,
},
components: {
GlBadge,
GlLoadingIcon,
GlIcon,
UserAccessRoleBadge,
identicon,
itemCaret,
itemTypeIcon,
itemStats,
itemStatsValue,
itemActions,
},
props: {
......@@ -91,6 +98,7 @@ export default {
}
},
},
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
};
</script>
......@@ -140,28 +148,31 @@ export default {
data-testid="group-name"
:href="group.relativePath"
:title="group.fullName"
class="no-expand gl-mt-3 gl-mr-3 gl-text-gray-900!"
class="no-expand gl-mr-3 gl-mt-3 gl-text-gray-900!"
:itemprop="microdata.nameItemprop"
>{{
>
{{
// ending bracket must be by closing tag to prevent
// link hover text-decoration from over-extending
group.name
}}</a
>
<item-stats-value
:icon-name="visibilityIcon"
}}
</a>
<gl-icon
v-gl-tooltip.hover.bottom
class="gl-display-inline-flex gl-align-items-center gl-mr-3 gl-mt-3 gl-text-gray-500"
:name="visibilityIcon"
:title="visibilityTooltip"
css-class="item-visibility d-inline-flex align-items-center gl-mt-3 gl-mr-2 text-secondary"
data-testid="group-visibility-icon"
/>
<span v-if="group.permission" class="user-access-role gl-mt-3">
<user-access-role-badge v-if="group.permission" class="gl-mt-3">
{{ group.permission }}
</span>
</user-access-role-badge>
</div>
<div v-if="group.description" class="description">
<span
v-safe-html:[$options.safeHtmlConfig]="group.description"
:itemprop="microdata.descriptionItemprop"
data-testid="group-description"
v-html="group.description"
>
</span>
</div>
......
......@@ -7,6 +7,7 @@ import { deprecatedCreateFlash as flash } from '~/flash';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import { __, sprintf } from '~/locale';
import eventHub from '~/sidebar/event_hub';
import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
import { splitCamelCase } from '../../lib/utils/text_utility';
import ReplyButton from './note_actions/reply_button.vue';
......@@ -17,6 +18,7 @@ export default {
ReplyButton,
GlButton,
GlDropdownItem,
UserAccessRoleBadge,
},
directives: {
GlTooltip: GlTooltipDirective,
......@@ -226,24 +228,30 @@ export default {
<template>
<div class="note-actions">
<span
<user-access-role-badge
v-if="isAuthor"
class="note-role user-access-role has-tooltip d-none d-md-inline-block"
v-gl-tooltip
class="gl-mx-3 d-none d-md-inline-block"
:title="displayAuthorBadgeText"
>{{ __('Author') }}</span
>
<span
{{ __('Author') }}
</user-access-role-badge>
<user-access-role-badge
v-if="accessLevel"
class="note-role user-access-role has-tooltip"
v-gl-tooltip
class="gl-mx-3"
:title="displayMemberBadgeText"
>{{ accessLevel }}</span
>
<span
{{ accessLevel }}
</user-access-role-badge>
<user-access-role-badge
v-else-if="isContributor"
class="note-role user-access-role has-tooltip"
v-gl-tooltip
class="gl-mx-3"
:title="displayContributorBadgeText"
>{{ __('Contributor') }}</span
>
{{ __('Contributor') }}
</user-access-role-badge>
<gl-button
v-if="canResolve"
ref="resolveButton"
......
......@@ -11,6 +11,7 @@ import {
} from '@gitlab/ui';
import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '~/groups/constants';
import csrf from '~/lib/utils/csrf';
import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
export default {
components: {
......@@ -20,6 +21,7 @@ export default {
GlButton,
GlTooltip,
GlLink,
UserAccessRoleBadge,
},
directives: {
GlTooltip: GlTooltipDirective,
......@@ -72,7 +74,9 @@ export default {
<template>
<li :class="rowClass" class="group-row">
<div class="group-row-contents gl-display-flex gl-align-items-center gl-py-3 gl-pr-5">
<div class="folder-toggle-wrap gl-mr-2 gl-display-flex gl-align-items-center">
<div
class="folder-toggle-wrap gl-mr-3 gl-display-flex gl-align-items-center gl-text-gray-500"
>
<gl-icon name="folder-o" />
</div>
<gl-link
......@@ -84,12 +88,12 @@ export default {
<div class="gl-min-w-0 gl-display-flex gl-flex-grow-1 gl-flex-shrink-1 gl-align-items-center">
<div class="gl-min-w-0 gl-flex-grow-1 flex-shrink-1">
<div class="title gl-display-flex gl-align-items-center gl-flex-wrap gl-mr-3">
<gl-link :href="group.relative_path" class="gl-mt-3 gl-mr-3 gl-text-gray-900!">{{
group.full_name
}}</gl-link>
<gl-link :href="group.relative_path" class="gl-mt-3 gl-mr-3 gl-text-gray-900!">
{{ group.full_name }}
</gl-link>
<gl-icon
v-gl-tooltip.hover.bottom
class="gl-mr-0 gl-inline-flex gl-mt-3 text-secondary"
class="gl-display-inline-flex gl-mt-3 gl-mr-3 gl-text-gray-500"
:name="visibilityIcon"
:title="visibilityTooltip"
/>
......@@ -99,11 +103,11 @@ export default {
class="gl-display-none gl-sm-display-flex gl-mt-3 gl-mr-1"
>{{ __('pending removal') }}</gl-badge
>
<span v-if="group.permission" class="user-access-role gl-mt-3">
<user-access-role-badge v-if="group.permission" class="gl-mt-3">
{{ group.permission }}
</span>
</user-access-role-badge>
</div>
<div v-if="group.description" class="description">
<div v-if="group.description" class="description gl-line-height-20">
<span v-safe-html="group.markdown_description"> </span>
</div>
</div>
......
<script>
/**
* This component applies particular styling to GlBadge that isn't
* available in the current GlBadge variants.
* Where possible, prefer one of the supported GlBadge variants.
* Discussion issue: https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1247
*/
import { GlBadge } from '@gitlab/ui';
export default {
name: 'UserAccessRoleBadge',
components: {
GlBadge,
},
};
</script>
<template>
<gl-badge class="gl-bg-transparent! gl-inset-border-1-gray-100!">
<slot></slot>
</gl-badge>
</template>
......@@ -519,10 +519,6 @@ table.pipeline-project-metrics tr td {
margin-left: 25px;
}
.item-visibility {
margin-right: 0;
}
.last-updated {
position: relative;
min-width: 250px;
......
---
title: Improve styling of user access role badges
merge_request: 56061
author:
type: changed
......@@ -188,7 +188,7 @@ describe('GroupItemComponent', () => {
});
it('should render component template correctly', () => {
const visibilityIconEl = vm.$el.querySelector('.item-visibility');
const visibilityIconEl = vm.$el.querySelector('[data-testid="group-visibility-icon"]');
expect(vm.$el.getAttribute('id')).toBe('group-55');
expect(vm.$el.classList.contains('group-row')).toBeTruthy();
......@@ -209,8 +209,7 @@ describe('GroupItemComponent', () => {
expect(vm.$el.querySelector('.title a.no-expand')).toBeDefined();
expect(visibilityIconEl).not.toBe(null);
expect(visibilityIconEl.title).toBe(vm.visibilityTooltip);
expect(visibilityIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
expect(visibilityIconEl.getAttribute('title')).toBe(vm.visibilityTooltip);
expect(vm.$el.querySelector('.access-type')).toBeDefined();
expect(vm.$el.querySelector('.description')).toBeDefined();
......
......@@ -6,6 +6,7 @@ import axios from '~/lib/utils/axios_utils';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
import noteActions from '~/notes/components/note_actions.vue';
import createStore from '~/notes/stores';
import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
import { userDataMock } from '../mock_data';
describe('noteActions', () => {
......@@ -15,6 +16,9 @@ describe('noteActions', () => {
let actions;
let axiosMock;
const findUserAccessRoleBadge = (idx) => wrapper.findAll(UserAccessRoleBadge).at(idx);
const findUserAccessRoleBadgeText = (idx) => findUserAccessRoleBadge(idx).text().trim();
const mountNoteActions = (propsData, computed) => {
const localVue = createLocalVue();
return mount(localVue.extend(noteActions), {
......@@ -66,11 +70,11 @@ describe('noteActions', () => {
});
it('should render noteable author badge', () => {
expect(wrapper.findAll('.note-role').at(0).text().trim()).toEqual('Author');
expect(findUserAccessRoleBadgeText(0)).toBe('Author');
});
it('should render access level badge', () => {
expect(wrapper.findAll('.note-role').at(1).text().trim()).toEqual(props.accessLevel);
expect(findUserAccessRoleBadgeText(1)).toBe(props.accessLevel);
});
it('should render contributor badge', () => {
......@@ -80,7 +84,7 @@ describe('noteActions', () => {
});
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.findAll('.note-role').at(1).text().trim()).toBe('Contributor');
expect(findUserAccessRoleBadgeText(1)).toBe('Contributor');
});
});
......
import { GlBadge } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
describe('UserAccessRoleBadge', () => {
let wrapper;
const createComponent = ({ slots } = {}) => {
wrapper = shallowMount(UserAccessRoleBadge, {
slots,
});
};
it('renders slot content inside GlBadge', () => {
createComponent({
slots: {
default: 'test slot content',
},
});
const badge = wrapper.find(GlBadge);
expect(badge.exists()).toBe(true);
expect(badge.html()).toContain('test slot content');
});
});
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