Commit 5f26b186 authored by Phil Hughes's avatar Phil Hughes

Added tabs to the code intelligence popover

https://gitlab.com/gitlab-org/gitlab/-/issues/217392
parent a04c8e24
<script> <script>
import { GlButton } from '@gitlab/ui'; import { GlButton, GlTabs, GlTab, GlLink, GlBadge } from '@gitlab/ui';
import DocLine from './doc_line.vue'; import DocLine from './doc_line.vue';
export default { export default {
components: { components: {
GlButton, GlButton,
GlTabs,
GlTab,
GlLink,
GlBadge,
DocLine, DocLine,
}, },
props: { props: {
...@@ -54,6 +58,9 @@ export default { ...@@ -54,6 +58,9 @@ export default {
isDefinitionCurrentBlob() { isDefinitionCurrentBlob() {
return this.data.definition_path.indexOf(this.blobPath) === 0; return this.data.definition_path.indexOf(this.blobPath) === 0;
}, },
references() {
return this.data.references || [];
},
}, },
watch: { watch: {
position: { position: {
...@@ -82,37 +89,61 @@ export default { ...@@ -82,37 +89,61 @@ export default {
class="popover code-navigation-popover popover-font-size-normal gl-popover bs-popover-bottom show" class="popover code-navigation-popover popover-font-size-normal gl-popover bs-popover-bottom show"
> >
<div :style="{ left: `${offsetLeft}px` }" class="arrow"></div> <div :style="{ left: `${offsetLeft}px` }" class="arrow"></div>
<div class="overflow-auto code-navigation-popover-container"> <gl-tabs nav-class="gl-hidden" content-class="gl-py-0">
<div <gl-tab :title="__('Definition')">
v-for="(hover, index) in data.hover" <div class="overflow-auto code-navigation-popover-container">
:key="index" <div
:class="{ 'border-bottom': index !== data.hover.length - 1 }" v-for="(hover, index) in data.hover"
> :key="index"
<pre :class="{ 'border-bottom': index !== data.hover.length - 1 }"
v-if="hover.language" >
ref="code-output" <pre
:class="$options.colorScheme" v-if="hover.language"
class="border-0 bg-transparent m-0 code highlight text-wrap" ref="code-output"
><doc-line v-for="(tokens, tokenIndex) in hover.tokens" :key="tokenIndex" :language="hover.language" :tokens="tokens"/></pre> :class="$options.colorScheme"
<p v-else ref="doc-output" class="p-3 m-0 gl-font-base"> class="border-0 bg-transparent m-0 code highlight text-wrap"
{{ hover.value }} ><doc-line v-for="(tokens, tokenIndex) in hover.tokens" :key="tokenIndex" :language="hover.language" :tokens="tokens"/></pre>
<p v-else ref="doc-output" class="p-3 m-0">
{{ hover.value }}
</p>
</div>
</div>
<div v-if="definitionPath || isCurrentDefinition" class="popover-body border-top">
<span v-if="isCurrentDefinition" class="gl-font-weight-bold gl-font-base">
{{ s__('CodeIntelligence|This is the definition') }}
</span>
<gl-button
v-else
:href="definitionPath"
:target="isDefinitionCurrentBlob ? null : '_blank'"
class="w-100"
variant="default"
data-testid="go-to-definition-btn"
>
{{ __('Go to definition') }}
</gl-button>
</div>
</gl-tab>
<gl-tab data-testid="references-tab" class="py-2">
<template #title>
{{ __('References') }}
<gl-badge size="sm" class="gl-tab-counter-badge">{{ references.length }}</gl-badge>
</template>
<template v-if="references.length">
<div v-for="(reference, index) in references" :key="index" class="gl-dropdown-item">
<gl-link
:href="`${definitionPathPrefix}/${reference.path}`"
class="dropdown-item"
data-testid="reference-link"
>
{{ reference.path }}
</gl-link>
</div>
</template>
<p v-else class="gl-my-4 gl-px-4">
{{ s__('CodeNavigation|No references found') }}
</p> </p>
</div> </gl-tab>
</div> </gl-tabs>
<div v-if="definitionPath || isCurrentDefinition" class="popover-body border-top">
<span v-if="isCurrentDefinition" class="gl-font-weight-bold gl-font-base">
{{ s__('CodeIntelligence|This is the definition') }}
</span>
<gl-button
v-else
:href="definitionPath"
:target="isDefinitionCurrentBlob ? null : '_blank'"
class="w-100"
variant="default"
data-testid="go-to-definition-btn"
>
{{ __('Go to definition') }}
</gl-button>
</div>
</div> </div>
</template> </template>
...@@ -5882,6 +5882,9 @@ msgstr "" ...@@ -5882,6 +5882,9 @@ msgstr ""
msgid "CodeIntelligence|This is the definition" msgid "CodeIntelligence|This is the definition"
msgstr "" msgstr ""
msgid "CodeNavigation|No references found"
msgstr ""
msgid "CodeOwner|Pattern" msgid "CodeOwner|Pattern"
msgstr "" msgstr ""
...@@ -7512,6 +7515,9 @@ msgstr "" ...@@ -7512,6 +7515,9 @@ msgstr ""
msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here." msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
msgstr "" msgstr ""
msgid "Definition"
msgstr ""
msgid "Delayed Project Deletion (%{adjourned_deletion})" msgid "Delayed Project Deletion (%{adjourned_deletion})"
msgstr "" msgstr ""
...@@ -19170,6 +19176,9 @@ msgstr "" ...@@ -19170,6 +19176,9 @@ msgstr ""
msgid "Reference:" msgid "Reference:"
msgstr "" msgstr ""
msgid "References"
msgstr ""
msgid "Refresh" msgid "Refresh"
msgstr "" msgstr ""
......
...@@ -10,57 +10,81 @@ exports[`Code navigation popover component renders popover 1`] = ` ...@@ -10,57 +10,81 @@ exports[`Code navigation popover component renders popover 1`] = `
style="left: 0px;" style="left: 0px;"
/> />
<div <gl-tabs-stub
class="overflow-auto code-navigation-popover-container" contentclass="gl-py-0"
nav-class="gl-hidden"
theme="indigo"
> >
<div <gl-tab-stub
class="" title="Definition"
> >
<pre <div
class="border-0 bg-transparent m-0 code highlight text-wrap" class="overflow-auto code-navigation-popover-container"
> >
<span <div
class="line" class=""
lang="javascript"
> >
<span <pre
class="k" class="border-0 bg-transparent m-0 code highlight text-wrap"
> >
function <span
</span> class="line"
<span> lang="javascript"
main() { >
</span> <span
</span> class="k"
<span >
class="line" function
lang="javascript" </span>
<span>
main() {
</span>
</span>
<span
class="line"
lang="javascript"
>
<span>
}
</span>
</span>
</pre>
</div>
</div>
<div
class="popover-body border-top"
>
<gl-button-stub
category="tertiary"
class="w-100"
data-testid="go-to-definition-btn"
href="http://gitlab.com/test.js"
icon=""
size="medium"
target="_blank"
variant="default"
> >
<span>
} Go to definition
</span>
</span> </gl-button-stub>
</pre> </div>
</div> </gl-tab-stub>
</div>
<gl-tab-stub
<div class="py-2"
class="popover-body border-top" data-testid="references-tab"
>
<gl-button-stub
category="tertiary"
class="w-100"
data-testid="go-to-definition-btn"
href="http://gitlab.com/test.js"
icon=""
size="medium"
target="_blank"
variant="default"
> >
<p
class="gl-my-4 gl-px-4"
>
No references found
Go to definition </p>
</gl-tab-stub>
</gl-button-stub> </gl-tabs-stub>
</div>
</div> </div>
`; `;
...@@ -40,6 +40,17 @@ const MOCK_DOCS_DATA = Object.freeze({ ...@@ -40,6 +40,17 @@ const MOCK_DOCS_DATA = Object.freeze({
definition_path: 'test.js#L20', definition_path: 'test.js#L20',
}); });
const MOCK_DATA_WITH_REFERENCES = Object.freeze({
hover: [
{
language: null,
value: 'console.log',
},
],
references: [{ path: 'index.js' }, { path: 'app.js' }],
definition_path: 'test.js#L20',
});
let wrapper; let wrapper;
function factory({ position, data, definitionPathPrefix, blobPath = 'index.js' }) { function factory({ position, data, definitionPathPrefix, blobPath = 'index.js' }) {
...@@ -64,6 +75,16 @@ describe('Code navigation popover component', () => { ...@@ -64,6 +75,16 @@ describe('Code navigation popover component', () => {
expect(wrapper.element).toMatchSnapshot(); expect(wrapper.element).toMatchSnapshot();
}); });
it('srender references tab with empty text when no references exist', () => {
factory({
position: { x: 0, y: 0, height: 0 },
data: MOCK_CODE_DATA,
definitionPathPrefix: DEFINITION_PATH_PREFIX,
});
expect(wrapper.find('[data-testid="references-tab"]').text()).toContain('No references found');
});
it('renders link with hash to current file', () => { it('renders link with hash to current file', () => {
factory({ factory({
position: { x: 0, y: 0, height: 0 }, position: { x: 0, y: 0, height: 0 },
...@@ -75,6 +96,17 @@ describe('Code navigation popover component', () => { ...@@ -75,6 +96,17 @@ describe('Code navigation popover component', () => {
expect(wrapper.find('[data-testid="go-to-definition-btn"]').attributes('href')).toBe('#L20'); expect(wrapper.find('[data-testid="go-to-definition-btn"]').attributes('href')).toBe('#L20');
}); });
it('renders list of references', () => {
factory({
position: { x: 0, y: 0, height: 0 },
data: MOCK_DATA_WITH_REFERENCES,
definitionPathPrefix: DEFINITION_PATH_PREFIX,
});
expect(wrapper.find('[data-testid="references-tab"]').exists()).toBe(true);
expect(wrapper.findAll('[data-testid="reference-link"]').length).toBe(2);
});
describe('code output', () => { describe('code output', () => {
it('renders code output', () => { it('renders code output', () => {
factory({ factory({
......
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