Commit 41f33d9d authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'ph/widgetExtensionsTertiaryButtons' into 'master'

Adds support for tertiary buttons inside of the widget extension

See merge request gitlab-org/gitlab!71097
parents c1d94239 bf4a58f5
<script>
import { GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { sprintf, __ } from '~/locale';
export default {
components: {
GlButton,
GlDropdown,
GlDropdownItem,
},
props: {
widget: {
type: String,
required: true,
},
tertiaryButtons: {
type: Array,
required: false,
default: () => [],
},
},
computed: {
dropdownLabel() {
return sprintf(__('%{widget} options'), { widget: this.widget });
},
},
};
</script>
<template>
<div>
<gl-dropdown
:text="dropdownLabel"
icon="ellipsis_v"
no-caret
category="tertiary"
right
lazy
text-sr-only
size="small"
class="gl-display-block gl-md-display-none!"
>
<gl-dropdown-item
v-for="(btn, index) in tertiaryButtons"
:key="index"
:href="btn.href"
:target="btn.target"
>
{{ btn.text }}
</gl-dropdown-item>
</gl-dropdown>
<template v-if="tertiaryButtons.length">
<gl-button
v-for="(btn, index) in tertiaryButtons"
:key="index"
:href="btn.href"
:target="btn.target"
:class="{ 'gl-mr-3': index > 1 }"
category="tertiary"
variant="confirm"
size="small"
class="gl-display-none gl-md-display-block"
>
{{ btn.text }}
</gl-button>
</template>
</div>
</template>
...@@ -11,6 +11,7 @@ import { sprintf, s__ } from '~/locale'; ...@@ -11,6 +11,7 @@ import { sprintf, s__ } from '~/locale';
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue'; import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
import { EXTENSION_ICON_CLASS } from '../../constants'; import { EXTENSION_ICON_CLASS } from '../../constants';
import StatusIcon from './status_icon.vue'; import StatusIcon from './status_icon.vue';
import Actions from './actions.vue';
export const LOADING_STATES = { export const LOADING_STATES = {
collapsedLoading: 'collapsedLoading', collapsedLoading: 'collapsedLoading',
...@@ -26,6 +27,7 @@ export default { ...@@ -26,6 +27,7 @@ export default {
GlBadge, GlBadge,
SmartVirtualList, SmartVirtualList,
StatusIcon, StatusIcon,
Actions,
}, },
directives: { directives: {
SafeHtml: GlSafeHtmlDirective, SafeHtml: GlSafeHtmlDirective,
...@@ -66,6 +68,9 @@ export default { ...@@ -66,6 +68,9 @@ export default {
return this.statusIcon(this.collapsedData); return this.statusIcon(this.collapsedData);
}, },
tertiaryActionsButtons() {
return this.tertiaryButtons ? this.tertiaryButtons() : undefined;
},
}, },
watch: { watch: {
isCollapsed(newVal) { isCollapsed(newVal) {
...@@ -119,13 +124,16 @@ export default { ...@@ -119,13 +124,16 @@ export default {
:is-loading="isLoadingSummary" :is-loading="isLoadingSummary"
:icon-name="statusIconName" :icon-name="statusIconName"
/> />
<div class="media-body gl-display-flex gl-align-self-center gl-align-items-center"> <div
<div class="code-text"> class="media-body gl-display-flex gl-align-self-center gl-align-items-center gl-flex-direction-row!"
>
<div class="gl-flex-grow-1">
<template v-if="isLoadingSummary"> <template v-if="isLoadingSummary">
{{ __('Loading...') }} {{ __('Loading...') }}
</template> </template>
<div v-else v-safe-html="summary(collapsedData)"></div> <div v-else v-safe-html="summary(collapsedData)"></div>
</div> </div>
<actions :widget="$options.name" :tertiary-buttons="tertiaryActionsButtons" />
<div <div
class="gl-float-right gl-align-self-center gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3" class="gl-float-right gl-align-self-center gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3"
> >
...@@ -138,6 +146,7 @@ export default { ...@@ -138,6 +146,7 @@ export default {
:icon="isCollapsed ? 'chevron-lg-down' : 'chevron-lg-up'" :icon="isCollapsed ? 'chevron-lg-down' : 'chevron-lg-up'"
category="tertiary" category="tertiary"
data-testid="toggle-button" data-testid="toggle-button"
size="small"
@click="toggleCollapsed" @click="toggleCollapsed"
/> />
</div> </div>
......
...@@ -9,7 +9,7 @@ export default { ...@@ -9,7 +9,7 @@ export default {
name: 'Issues', name: 'Issues',
// Add an array of props // Add an array of props
// These then get mapped to values stored in the MR Widget store // These then get mapped to values stored in the MR Widget store
props: ['targetProjectFullPath'], props: ['targetProjectFullPath', 'conflictsDocsPath'],
// Add any extra computed props in here // Add any extra computed props in here
computed: { computed: {
// Small summary text to be displayed in the collapsed state // Small summary text to be displayed in the collapsed state
...@@ -22,6 +22,11 @@ export default { ...@@ -22,6 +22,11 @@ export default {
statusIcon(count) { statusIcon(count) {
return EXTENSION_ICONS.warning; return EXTENSION_ICONS.warning;
}, },
// Tertiary action buttons that will take the user elsewhere
// in the GitLab app
tertiaryButtons() {
return [{ text: 'Full report', href: this.conflictsDocsPath, target: '_blank' }];
},
}, },
methods: { methods: {
// Fetches the collapsed data // Fetches the collapsed data
......
...@@ -1055,6 +1055,9 @@ msgstr "" ...@@ -1055,6 +1055,9 @@ msgstr ""
msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook." msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project. We recommend using an %{integrations_link_start}integration%{link_end} in preference to a webhook."
msgstr "" msgstr ""
msgid "%{widget} options"
msgstr ""
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported." msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr "" msgstr ""
......
import { GlButton, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Actions from '~/vue_merge_request_widget/components/extensions/actions.vue';
let wrapper;
function factory(propsData = {}) {
wrapper = shallowMount(Actions, {
propsData: { ...propsData, widget: 'test' },
});
}
describe('MR widget extension actions', () => {
afterEach(() => {
wrapper.destroy();
});
describe('tertiaryButtons', () => {
it('renders buttons', () => {
factory({
tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
});
expect(wrapper.findAllComponents(GlButton)).toHaveLength(1);
});
it('renders tertiary actions in dropdown', () => {
factory({
tertiaryButtons: [{ text: 'hello world', href: 'https://gitlab.com', target: '_blank' }],
});
expect(wrapper.findAllComponents(GlDropdownItem)).toHaveLength(1);
});
});
});
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