Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_merge_request_widget/components/widget')
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue134
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue44
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue35
6 files changed, 198 insertions, 33 deletions
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue
new file mode 100644
index 00000000000..6655af92a55
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/action_buttons.vue
@@ -0,0 +1,134 @@
+<script>
+import { GlButton, GlDropdown, GlDropdownItem, GlTooltipDirective } from '@gitlab/ui';
+import { sprintf, __ } from '~/locale';
+
+export default {
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ widget: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ tertiaryButtons: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ data: () => {
+ return {
+ timeout: null,
+ updatingTooltip: false,
+ };
+ },
+ computed: {
+ dropdownLabel() {
+ if (!this.widget) return undefined;
+
+ return sprintf(__('%{widget} options'), { widget: this.widget });
+ },
+ },
+ methods: {
+ onClickAction(action) {
+ this.$emit('clickedAction', action);
+
+ if (action.onClick) {
+ action.onClick();
+ }
+
+ if (action.tooltipOnClick) {
+ this.updatingTooltip = true;
+ this.$root.$emit('bv::show::tooltip', action.id);
+
+ clearTimeout(this.timeout);
+
+ this.timeout = setTimeout(() => {
+ this.updatingTooltip = false;
+ this.$root.$emit('bv::hide::tooltip', action.id);
+ }, 1000);
+ }
+ },
+ setTooltip(btn) {
+ if (this.updatingTooltip && btn.tooltipOnClick) {
+ return btn.tooltipOnClick;
+ }
+
+ return btn.tooltipText;
+ },
+ actionButtonQaSelector(btn) {
+ if (btn.dataQaSelector) {
+ return btn.dataQaSelector;
+ }
+ return 'mr_widget_extension_actions_button';
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-flex-start">
+ <gl-dropdown
+ v-if="tertiaryButtons.length"
+ v-gl-tooltip
+ :title="__('Options')"
+ :text="dropdownLabel"
+ icon="ellipsis_v"
+ no-caret
+ category="tertiary"
+ right
+ lazy
+ text-sr-only
+ size="small"
+ toggle-class="gl-p-2!"
+ 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"
+ :data-clipboard-text="btn.dataClipboardText"
+ :data-method="btn.dataMethod"
+ @click="onClickAction(btn)"
+ >
+ {{ btn.text }}
+ </gl-dropdown-item>
+ </gl-dropdown>
+ <template v-if="tertiaryButtons.length">
+ <gl-button
+ v-for="(btn, index) in tertiaryButtons"
+ :id="btn.id"
+ :key="index"
+ v-gl-tooltip.hover
+ :title="setTooltip(btn)"
+ :href="btn.href"
+ :target="btn.target"
+ :class="[{ 'gl-mr-3': index !== tertiaryButtons.length - 1 }, btn.class]"
+ :data-clipboard-text="btn.dataClipboardText"
+ :data-qa-selector="actionButtonQaSelector(btn)"
+ :data-method="btn.dataMethod"
+ :icon="btn.icon"
+ :data-testid="btn.testId || 'extension-actions-button'"
+ :variant="btn.variant || 'confirm'"
+ :loading="btn.loading"
+ :disabled="btn.loading"
+ category="tertiary"
+ size="small"
+ class="gl-display-none gl-md-display-block gl-float-left"
+ @click="onClickAction(btn)"
+ >
+ <template v-if="btn.text">
+ {{ btn.text }}
+ </template>
+ </gl-button>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
index 2f52ac70833..18aa85484ea 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
@@ -20,13 +20,14 @@ export default {
role="region"
:aria-label="__('Merge request reports')"
data-testid="mr-widget-app"
+ class="mr-widget-section"
>
<component
:is="widget"
v-for="(widget, index) in widgets"
:key="widget.name || index"
:mr="mr"
- :class="{ 'mr-widget-border-top': index === 0 }"
+ class="mr-widget-section"
/>
</section>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue
index 4d66c75719b..cdce7c6625a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/dynamic_content.vue
@@ -1,8 +1,9 @@
<script>
-import { GlBadge, GlLink, GlSafeHtmlDirective } from '@gitlab/ui';
-import Actions from '../action_buttons.vue';
+import { GlBadge, GlLink } from '@gitlab/ui';
+import SafeHtml from '~/vue_shared/directives/safe_html';
import { generateText } from '../extensions/utils';
import ContentRow from './widget_content_row.vue';
+import Actions from './action_buttons.vue';
export default {
name: 'DynamicContent',
@@ -13,7 +14,7 @@ export default {
ContentRow,
},
directives: {
- SafeHtml: GlSafeHtmlDirective,
+ SafeHtml,
},
props: {
data: {
@@ -81,10 +82,8 @@ export default {
v-if="data.children && data.children.length > 0 && level === 2"
class="gl-m-0 gl-p-0 gl-list-style-none"
>
- <li>
+ <li v-for="(childData, index) in data.children" :key="childData.id || index">
<dynamic-content
- v-for="(childData, index) in data.children"
- :key="childData.id || index"
:data="childData"
:widget-name="widgetName"
:level="3"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue
index 181b8cfad9a..6d17ac98d7f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/status_icon.vue
@@ -48,9 +48,9 @@ export default {
:class="{
[iconClassNameText]: !isLoading,
[`mr-widget-status-icon-level-${level}`]: !isLoading,
- 'gl-mr-3': level === 1,
+ 'gl-w-6 gl-h-6 gl--flex-center': level === 1,
}"
- class="gl-relative gl-w-6 gl-h-6 gl-rounded-full gl--flex-center"
+ class="gl-relative gl-rounded-full gl-mr-3"
>
<gl-loading-icon v-if="isLoading" size="md" inline />
<gl-icon
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
index cea7fb8260a..cdf35033021 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
@@ -1,22 +1,18 @@
<script>
-import {
- GlButton,
- GlLink,
- GlTooltipDirective,
- GlLoadingIcon,
- GlSafeHtmlDirective,
-} from '@gitlab/ui';
+import { GlButton, GlLink, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import { normalizeHeaders } from '~/lib/utils/common_utils';
+import SafeHtml from '~/vue_shared/directives/safe_html';
import { sprintf, __ } from '~/locale';
import Poll from '~/lib/utils/poll';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
-import ActionButtons from '../action_buttons.vue';
+import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller';
import { EXTENSION_ICONS } from '../../constants';
import { createTelemetryHub } from '../extensions/telemetry';
import ContentRow from './widget_content_row.vue';
import DynamicContent from './dynamic_content.vue';
import StatusIcon from './status_icon.vue';
+import ActionButtons from './action_buttons.vue';
const FETCH_TYPE_COLLAPSED = 'collapsed';
const FETCH_TYPE_EXPANDED = 'expanded';
@@ -31,11 +27,13 @@ export default {
GlLoadingIcon,
ContentRow,
DynamicContent,
+ DynamicScroller,
+ DynamicScrollerItem,
HelpPopover,
},
directives: {
GlTooltip: GlTooltipDirective,
- SafeHtml: GlSafeHtmlDirective,
+ SafeHtml,
},
props: {
/**
@@ -258,6 +256,7 @@ export default {
<div class="gl-display-flex">
<help-popover
v-if="helpPopover"
+ icon="information-o"
:options="helpPopover.options"
:class="{ 'gl-mr-3': actionButtons.length > 0 }"
>
@@ -309,7 +308,7 @@ export default {
<div v-if="isLoadingExpandedContent" class="report-block-container gl-text-center">
<gl-loading-icon size="sm" inline /> {{ loadingText }}
</div>
- <div v-else class="gl-px-5 gl-display-flex">
+ <div v-else class="gl-pl-5 gl-display-flex" :class="{ 'gl-pr-5': $scopedSlots.content }">
<content-row
v-if="contentError"
:level="2"
@@ -322,12 +321,25 @@ export default {
</content-row>
<div v-else class="gl-w-full">
<slot name="content">
- <dynamic-content
- v-for="(data, index) in content"
- :key="data.id || index"
- :data="data"
- :widget-name="widgetName"
- />
+ <dynamic-scroller
+ v-if="content"
+ :items="content"
+ :min-item-size="32"
+ :style="{ maxHeight: '170px' }"
+ data-testid="dynamic-content-scroller"
+ class="gl-pr-5"
+ >
+ <template #default="{ item, index, active }">
+ <dynamic-scroller-item :item="item" :active="active">
+ <dynamic-content
+ :key="item.id || index"
+ :data="item"
+ :widget-name="widgetName"
+ :level="2"
+ />
+ </dynamic-scroller-item>
+ </template>
+ </dynamic-scroller>
</slot>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue
index 1fd1e325863..543136dc659 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget_content_row.vue
@@ -1,10 +1,11 @@
<script>
-import { GlSafeHtmlDirective, GlLink } from '@gitlab/ui';
+import { GlLink } from '@gitlab/ui';
import { __ } from '~/locale';
import HelpPopover from '~/vue_shared/components/help_popover.vue';
-import ActionButtons from '../action_buttons.vue';
+import SafeHtml from '~/vue_shared/directives/safe_html';
import { EXTENSION_ICONS } from '../../constants';
import { generateText } from '../extensions/utils';
+import ActionButtons from './action_buttons.vue';
import StatusIcon from './status_icon.vue';
export default {
@@ -15,7 +16,7 @@ export default {
ActionButtons,
},
directives: {
- SafeHtml: GlSafeHtmlDirective,
+ SafeHtml,
},
props: {
level: {
@@ -67,6 +68,9 @@ export default {
shouldShowHeaderActions() {
return Boolean(this.helpPopover) || this.actionButtons?.length > 0;
},
+ hasActionButtons() {
+ return this.actionButtons.length > 0;
+ },
},
i18n: {
learnMore: __('Learn more'),
@@ -75,10 +79,15 @@ export default {
</script>
<template>
<div
- class="gl-w-full gl-display-flex mr-widget-content-row gl-align-items-baseline"
+ class="gl-w-full gl-display-flex gl-align-items-baseline"
:class="{ 'gl-border-t gl-py-3 gl-pl-7': level === 2 }"
>
- <status-icon v-if="statusIconName" :level="2" :name="widgetName" :icon-name="statusIconName" />
+ <status-icon
+ v-if="statusIconName && !header"
+ :level="2"
+ :name="widgetName"
+ :icon-name="statusIconName"
+ />
<div class="gl-w-full">
<div class="gl-display-flex">
<slot name="header">
@@ -95,7 +104,12 @@ export default {
v-if="shouldShowHeaderActions"
class="gl-ml-auto gl-display-flex gl-align-items-baseline"
>
- <help-popover v-if="helpPopover" :options="helpPopover.options">
+ <help-popover
+ v-if="helpPopover"
+ :options="helpPopover.options"
+ :class="{ 'gl-mr-3': hasActionButtons }"
+ icon="information-o"
+ >
<template v-if="helpPopover.content">
<p
v-if="helpPopover.content.text"
@@ -112,14 +126,19 @@ export default {
</template>
</help-popover>
<action-buttons
- v-if="actionButtons.length > 0"
+ v-if="hasActionButtons"
:widget="widgetName"
:tertiary-buttons="actionButtons"
- :class="{ 'gl-ml-2': helpPopover }"
/>
</div>
</div>
<div class="gl-display-flex gl-align-items-baseline gl-w-full">
+ <status-icon
+ v-if="statusIconName && header"
+ :level="2"
+ :name="widgetName"
+ :icon-name="statusIconName"
+ />
<slot name="body"></slot>
</div>
</div>