2020-10-27 12:08:33 +00:00
|
|
|
<script>
|
2021-10-01 09:11:45 +00:00
|
|
|
import {
|
|
|
|
GlButton,
|
|
|
|
GlLoadingIcon,
|
|
|
|
GlLink,
|
|
|
|
GlBadge,
|
|
|
|
GlSafeHtmlDirective,
|
|
|
|
GlTooltipDirective,
|
|
|
|
} from '@gitlab/ui';
|
|
|
|
import { sprintf, s__ } from '~/locale';
|
2020-10-27 12:08:33 +00:00
|
|
|
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
|
2021-09-29 12:11:22 +00:00
|
|
|
import { EXTENSION_ICON_CLASS } from '../../constants';
|
|
|
|
import StatusIcon from './status_icon.vue';
|
2020-10-27 12:08:33 +00:00
|
|
|
|
|
|
|
export const LOADING_STATES = {
|
|
|
|
collapsedLoading: 'collapsedLoading',
|
|
|
|
collapsedError: 'collapsedError',
|
|
|
|
expandedLoading: 'expandedLoading',
|
|
|
|
};
|
|
|
|
|
|
|
|
export default {
|
|
|
|
components: {
|
|
|
|
GlButton,
|
|
|
|
GlLoadingIcon,
|
|
|
|
GlLink,
|
|
|
|
GlBadge,
|
|
|
|
SmartVirtualList,
|
|
|
|
StatusIcon,
|
|
|
|
},
|
|
|
|
directives: {
|
|
|
|
SafeHtml: GlSafeHtmlDirective,
|
2021-10-01 09:11:45 +00:00
|
|
|
GlTooltip: GlTooltipDirective,
|
2020-10-27 12:08:33 +00:00
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
loadingState: LOADING_STATES.collapsedLoading,
|
|
|
|
collapsedData: null,
|
|
|
|
fullData: null,
|
|
|
|
isCollapsed: true,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
isLoadingSummary() {
|
|
|
|
return this.loadingState === LOADING_STATES.collapsedLoading;
|
|
|
|
},
|
|
|
|
isLoadingExpanded() {
|
|
|
|
return this.loadingState === LOADING_STATES.expandedLoading;
|
|
|
|
},
|
|
|
|
isCollapsible() {
|
|
|
|
if (this.isLoadingSummary) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
2021-10-01 09:11:45 +00:00
|
|
|
collapseButtonLabel() {
|
|
|
|
return sprintf(
|
|
|
|
this.isCollapsed
|
|
|
|
? s__('mrWidget|Show %{widget} details')
|
|
|
|
: s__('mrWidget|Hide %{widget} details'),
|
|
|
|
{ widget: this.$options.name },
|
|
|
|
);
|
|
|
|
},
|
2020-10-27 12:08:33 +00:00
|
|
|
statusIconName() {
|
2021-09-29 15:11:47 +00:00
|
|
|
if (this.isLoadingSummary) return null;
|
|
|
|
|
2020-10-27 12:08:33 +00:00
|
|
|
return this.statusIcon(this.collapsedData);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
watch: {
|
|
|
|
isCollapsed(newVal) {
|
|
|
|
if (!newVal) {
|
|
|
|
this.loadAllData();
|
|
|
|
} else {
|
|
|
|
this.loadingState = null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
mounted() {
|
|
|
|
this.fetchCollapsedData(this.$props)
|
2020-12-23 21:10:24 +00:00
|
|
|
.then((data) => {
|
2020-10-27 12:08:33 +00:00
|
|
|
this.collapsedData = data;
|
|
|
|
this.loadingState = null;
|
|
|
|
})
|
2020-12-23 21:10:24 +00:00
|
|
|
.catch((e) => {
|
2020-10-27 12:08:33 +00:00
|
|
|
this.loadingState = LOADING_STATES.collapsedError;
|
|
|
|
throw e;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
toggleCollapsed() {
|
|
|
|
this.isCollapsed = !this.isCollapsed;
|
|
|
|
},
|
|
|
|
loadAllData() {
|
|
|
|
if (this.fullData) return;
|
|
|
|
|
|
|
|
this.loadingState = LOADING_STATES.expandedLoading;
|
|
|
|
|
|
|
|
this.fetchFullData(this.$props)
|
2020-12-23 21:10:24 +00:00
|
|
|
.then((data) => {
|
2020-10-27 12:08:33 +00:00
|
|
|
this.loadingState = null;
|
|
|
|
this.fullData = data;
|
|
|
|
})
|
2020-12-23 21:10:24 +00:00
|
|
|
.catch((e) => {
|
2020-10-27 12:08:33 +00:00
|
|
|
this.loadingState = null;
|
|
|
|
throw e;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
2021-09-29 12:11:22 +00:00
|
|
|
EXTENSION_ICON_CLASS,
|
2020-10-27 12:08:33 +00:00
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2021-09-29 12:11:22 +00:00
|
|
|
<section class="media-section mr-widget-border-top" data-testid="widget-extension">
|
2020-10-27 12:08:33 +00:00
|
|
|
<div class="media gl-p-5">
|
2021-09-29 12:11:22 +00:00
|
|
|
<status-icon
|
|
|
|
:name="$options.name"
|
|
|
|
:is-loading="isLoadingSummary"
|
|
|
|
:icon-name="statusIconName"
|
|
|
|
/>
|
2021-10-01 09:11:45 +00:00
|
|
|
<div class="media-body gl-display-flex gl-align-self-center gl-align-items-center">
|
2020-10-27 12:08:33 +00:00
|
|
|
<div class="code-text">
|
|
|
|
<template v-if="isLoadingSummary">
|
|
|
|
{{ __('Loading...') }}
|
|
|
|
</template>
|
|
|
|
<div v-else v-safe-html="summary(collapsedData)"></div>
|
|
|
|
</div>
|
2021-10-01 09:11:45 +00:00
|
|
|
<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"
|
2020-10-27 12:08:33 +00:00
|
|
|
>
|
2021-10-01 09:11:45 +00:00
|
|
|
<gl-button
|
|
|
|
v-if="isCollapsible"
|
|
|
|
v-gl-tooltip
|
|
|
|
:title="collapseButtonLabel"
|
|
|
|
:aria-expanded="`${!isCollapsed}`"
|
|
|
|
:aria-label="collapseButtonLabel"
|
|
|
|
:icon="isCollapsed ? 'chevron-lg-down' : 'chevron-lg-up'"
|
|
|
|
category="tertiary"
|
|
|
|
data-testid="toggle-button"
|
|
|
|
@click="toggleCollapsed"
|
|
|
|
/>
|
|
|
|
</div>
|
2020-10-27 12:08:33 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
2021-09-29 12:11:22 +00:00
|
|
|
<div
|
|
|
|
v-if="!isCollapsed"
|
|
|
|
class="mr-widget-grouped-section"
|
|
|
|
data-testid="widget-extension-collapsed-section"
|
|
|
|
>
|
2020-10-27 12:08:33 +00:00
|
|
|
<div v-if="isLoadingExpanded" class="report-block-container">
|
2021-07-07 09:08:35 +00:00
|
|
|
<gl-loading-icon size="sm" inline /> {{ __('Loading...') }}
|
2020-10-27 12:08:33 +00:00
|
|
|
</div>
|
|
|
|
<smart-virtual-list
|
|
|
|
v-else-if="fullData"
|
|
|
|
:length="fullData.length"
|
|
|
|
:remain="20"
|
|
|
|
:size="32"
|
|
|
|
wtag="ul"
|
|
|
|
wclass="report-block-list"
|
|
|
|
class="report-block-container"
|
|
|
|
>
|
2021-10-06 12:11:40 +00:00
|
|
|
<li
|
|
|
|
v-for="data in fullData"
|
|
|
|
:key="data.id"
|
|
|
|
class="gl-display-flex gl-align-items-center"
|
|
|
|
data-testid="extension-list-item"
|
|
|
|
>
|
2021-09-30 12:12:36 +00:00
|
|
|
<status-icon v-if="data.icon" :icon-name="data.icon.name" :size="12" />
|
2021-10-01 09:11:45 +00:00
|
|
|
<div class="gl-mt-2 gl-mb-2 gl-flex-wrap gl-align-self-center gl-display-flex">
|
2021-09-28 15:11:30 +00:00
|
|
|
<div v-safe-html="data.text" class="gl-mr-4"></div>
|
2020-10-27 12:08:33 +00:00
|
|
|
<div v-if="data.link">
|
|
|
|
<gl-link :href="data.link.href">{{ data.link.text }}</gl-link>
|
|
|
|
</div>
|
|
|
|
<gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'">
|
|
|
|
{{ data.badge.text }}
|
|
|
|
</gl-badge>
|
|
|
|
</div>
|
|
|
|
</li>
|
|
|
|
</smart-virtual-list>
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
</template>
|