Commit 6a551a1e authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-11-14

parents 06ef748d 2059e9f5
...@@ -32,6 +32,7 @@ export default { ...@@ -32,6 +32,7 @@ export default {
computed: { computed: {
...mapState('diffs', ['currentDiffFileId']), ...mapState('diffs', ['currentDiffFileId']),
...mapGetters(['isNotesFetched']), ...mapGetters(['isNotesFetched']),
...mapGetters('diffs', ['getDiffFileDiscussions']),
isCollapsed() { isCollapsed() {
return this.file.collapsed || false; return this.file.collapsed || false;
}, },
...@@ -57,12 +58,23 @@ export default { ...@@ -57,12 +58,23 @@ export default {
showLoadingIcon() { showLoadingIcon() {
return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed); return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed);
}, },
hasDiffLines() {
const { highlightedDiffLines, parallelDiffLines } = this.file;
return highlightedDiffLines && parallelDiffLines && parallelDiffLines.length > 0;
},
},
watch: {
'file.collapsed': function fileCollapsedWatch(newVal, oldVal) {
if (!newVal && oldVal && !this.hasDiffLines) {
this.handleLoadCollapsedDiff();
}
},
}, },
methods: { methods: {
...mapActions('diffs', ['loadCollapsedDiff', 'assignDiscussionsToDiff']), ...mapActions('diffs', ['loadCollapsedDiff', 'assignDiscussionsToDiff']),
handleToggle() { handleToggle() {
const { highlightedDiffLines, parallelDiffLines } = this.file; if (!this.hasDiffLines) {
if (!highlightedDiffLines && parallelDiffLines !== undefined && !parallelDiffLines.length) {
this.handleLoadCollapsedDiff(); this.handleLoadCollapsedDiff();
} else { } else {
this.file.collapsed = !this.file.collapsed; this.file.collapsed = !this.file.collapsed;
...@@ -81,7 +93,7 @@ export default { ...@@ -81,7 +93,7 @@ export default {
.then(() => { .then(() => {
requestIdleCallback( requestIdleCallback(
() => { () => {
this.assignDiscussionsToDiff(); this.assignDiscussionsToDiff(this.getDiffFileDiscussions(this.file));
}, },
{ timeout: 1000 }, { timeout: 1000 },
); );
......
...@@ -135,10 +135,6 @@ export default class FilteredSearchVisualTokens { ...@@ -135,10 +135,6 @@ export default class FilteredSearchVisualTokens {
} }
static updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) { static updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) {
if (tokenValue === 'none') {
return Promise.resolve();
}
const username = tokenValue.replace(/^@/, ''); const username = tokenValue.replace(/^@/, '');
return ( return (
UsersCache.retrieve(username) UsersCache.retrieve(username)
...@@ -184,7 +180,12 @@ export default class FilteredSearchVisualTokens { ...@@ -184,7 +180,12 @@ export default class FilteredSearchVisualTokens {
const tokenValueElement = tokenValueContainer.querySelector('.value'); const tokenValueElement = tokenValueContainer.querySelector('.value');
tokenValueElement.innerText = tokenValue; tokenValueElement.innerText = tokenValue;
if (tokenValue === 'none' || tokenValue === 'any') {
return;
}
const tokenType = tokenName.toLowerCase(); const tokenType = tokenName.toLowerCase();
if (tokenType === 'label') { if (tokenType === 'label') {
FilteredSearchVisualTokens.updateLabelTokenColor(tokenValueContainer, tokenValue); FilteredSearchVisualTokens.updateLabelTokenColor(tokenValueContainer, tokenValue);
} else if (tokenType === 'author' || tokenType === 'assignee') { } else if (tokenType === 'author' || tokenType === 'assignee') {
......
<script> <script>
import $ from 'jquery'; import { GlTooltipDirective, GlButton } from '@gitlab-org/gitlab-ui';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { dasherize } from '~/lib/utils/text_utility'; import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale'; import { __ } from '~/locale';
import createFlash from '~/flash'; import createFlash from '~/flash';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
/** /**
...@@ -20,23 +19,20 @@ import Icon from '~/vue_shared/components/icon.vue'; ...@@ -20,23 +19,20 @@ import Icon from '~/vue_shared/components/icon.vue';
export default { export default {
components: { components: {
Icon, Icon,
GlButton,
}, },
directives: { directives: {
tooltip, GlTooltip: GlTooltipDirective,
}, },
props: { props: {
tooltipText: { tooltipText: {
type: String, type: String,
required: true, required: true,
}, },
link: { link: {
type: String, type: String,
required: true, required: true,
}, },
actionIcon: { actionIcon: {
type: String, type: String,
required: true, required: true,
...@@ -47,7 +43,6 @@ export default { ...@@ -47,7 +43,6 @@ export default {
isDisabled: false, isDisabled: false,
}; };
}, },
computed: { computed: {
cssClass() { cssClass() {
const actionIconDash = dasherize(this.actionIcon); const actionIconDash = dasherize(this.actionIcon);
...@@ -62,8 +57,7 @@ export default { ...@@ -62,8 +57,7 @@ export default {
* *
*/ */
onClickAction() { onClickAction() {
$(this.$el).tooltip('hide'); this.$root.$emit('bv::hide::tooltip', `js-ci-action-${this.link}`);
this.isDisabled = true; this.isDisabled = true;
axios axios
...@@ -82,18 +76,16 @@ export default { ...@@ -82,18 +76,16 @@ export default {
}; };
</script> </script>
<template> <template>
<button <gl-button
v-tooltip :id="`js-ci-action-${link}`"
v-gl-tooltip="{ boundary: 'viewport' }"
:title="tooltipText" :title="tooltipText"
:class="cssClass" :class="cssClass"
:disabled="isDisabled" :disabled="isDisabled"
type="button"
class="js-ci-action btn btn-blank class="js-ci-action btn btn-blank
btn-transparent ci-action-icon-container ci-action-icon-wrapper" btn-transparent ci-action-icon-container ci-action-icon-wrapper"
data-container="body"
data-boundary="viewport"
@click="onClickAction" @click="onClickAction"
> >
<icon :name="actionIcon"/> <icon :name="actionIcon"/>
</button> </gl-button>
</template> </template>
<script> <script>
import $ from 'jquery'; import $ from 'jquery';
import { GlTooltipDirective } from '@gitlab-org/gitlab-ui';
import CiIcon from '~/vue_shared/components/ci_icon.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue';
import JobItem from './job_item.vue'; import JobItem from './job_item.vue';
import tooltip from '../../../vue_shared/directives/tooltip';
/** /**
* Renders the dropdown for the pipeline graph. * Renders the dropdown for the pipeline graph.
...@@ -12,32 +12,27 @@ import tooltip from '../../../vue_shared/directives/tooltip'; ...@@ -12,32 +12,27 @@ import tooltip from '../../../vue_shared/directives/tooltip';
*/ */
export default { export default {
directives: { directives: {
tooltip, GlTooltip: GlTooltipDirective,
}, },
components: { components: {
JobItem, JobItem,
CiIcon, CiIcon,
}, },
props: { props: {
group: { group: {
type: Object, type: Object,
required: true, required: true,
}, },
}, },
computed: { computed: {
tooltipText() { tooltipText() {
const { name, status } = this.group; const { name, status } = this.group;
return `${name} - ${status.label}`; return `${name} - ${status.label}`;
}, },
}, },
mounted() { mounted() {
this.stopDropdownClickPropagation(); this.stopDropdownClickPropagation();
}, },
methods: { methods: {
/** /**
* When the user right clicks or cmd/ctrl + click in the group name or the action icon * When the user right clicks or cmd/ctrl + click in the group name or the action icon
...@@ -65,12 +60,10 @@ export default { ...@@ -65,12 +60,10 @@ export default {
<template> <template>
<div class="ci-job-dropdown-container dropdown dropright"> <div class="ci-job-dropdown-container dropdown dropright">
<button <button
v-tooltip v-gl-tooltip.hover="{ boundary: 'viewport' }"
:title="tooltipText" :title="tooltipText"
type="button" type="button"
data-toggle="dropdown" data-toggle="dropdown"
data-container="body"
data-boundary="viewport"
data-display="static" data-display="static"
class="dropdown-menu-toggle build-content" class="dropdown-menu-toggle build-content"
> >
......
<script> <script>
import ActionComponent from './action_component.vue'; import ActionComponent from './action_component.vue';
import JobNameComponent from './job_name_component.vue'; import JobNameComponent from './job_name_component.vue';
import tooltip from '../../../vue_shared/directives/tooltip'; import { GlTooltipDirective, GlLink } from '@gitlab-org/gitlab-ui';
import { sprintf } from '~/locale'; import { sprintf } from '~/locale';
import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin'; import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
...@@ -34,9 +34,10 @@ export default { ...@@ -34,9 +34,10 @@ export default {
components: { components: {
ActionComponent, ActionComponent,
JobNameComponent, JobNameComponent,
GlLink,
}, },
directives: { directives: {
tooltip, GlTooltip: GlTooltipDirective,
}, },
mixins: [delayedJobMixin], mixins: [delayedJobMixin],
props: { props: {
...@@ -55,7 +56,6 @@ export default { ...@@ -55,7 +56,6 @@ export default {
default: Infinity, default: Infinity,
}, },
}, },
computed: { computed: {
status() { status() {
return this.job && this.job.status ? this.job.status : {}; return this.job && this.job.status ? this.job.status : {};
...@@ -88,7 +88,6 @@ export default { ...@@ -88,7 +88,6 @@ export default {
tooltipBoundary() { tooltipBoundary() {
return this.dropdownLength < 5 ? 'viewport' : null; return this.dropdownLength < 5 ? 'viewport' : null;
}, },
/** /**
* Verifies if the provided job has an action path * Verifies if the provided job has an action path
* *
...@@ -98,7 +97,6 @@ export default { ...@@ -98,7 +97,6 @@ export default {
return this.job.status && this.job.status.action && this.job.status.action.path; return this.job.status && this.job.status.action && this.job.status.action.path;
}, },
}, },
methods: { methods: {
pipelineActionRequestComplete() { pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete'); this.$emit('pipelineActionRequestComplete');
...@@ -108,30 +106,26 @@ export default { ...@@ -108,30 +106,26 @@ export default {
</script> </script>
<template> <template>
<div class="ci-job-component"> <div class="ci-job-component">
<a <gl-link
v-if="status.has_details" v-if="status.has_details"
v-tooltip v-gl-tooltip="{ boundary: tooltipBoundary }"
:href="status.details_path" :href="status.details_path"
:title="tooltipText" :title="tooltipText"
:class="cssClassJobName" :class="cssClassJobName"
:data-boundary="tooltipBoundary"
data-container="body"
class="js-pipeline-graph-job-link" class="js-pipeline-graph-job-link"
> >
<job-name-component <job-name-component
:name="job.name" :name="job.name"
:status="job.status" :status="job.status"
/> />
</a> </gl-link>
<div <div
v-else v-else
v-tooltip v-gl-tooltip
:title="tooltipText" :title="tooltipText"
:class="cssClassJobName" :class="cssClassJobName"
class="js-job-component-tooltip non-details-job-component" class="js-job-component-tooltip non-details-job-component"
data-container="body"
> >
<job-name-component <job-name-component
......
...@@ -13,18 +13,15 @@ export default { ...@@ -13,18 +13,15 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
groups: { groups: {
type: Array, type: Array,
required: true, required: true,
}, },
isFirstColumn: { isFirstColumn: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false, default: false,
}, },
stageConnectorClass: { stageConnectorClass: {
type: String, type: String,
required: false, required: false,
...@@ -36,16 +33,13 @@ export default { ...@@ -36,16 +33,13 @@ export default {
required: true, required: true,
}, },
}, },
methods: { methods: {
groupId(group) { groupId(group) {
return `ci-badge-${_.escape(group.name)}`; return `ci-badge-${_.escape(group.name)}`;
}, },
buildConnnectorClass(index) { buildConnnectorClass(index) {
return index === 0 && (!this.isFirstColumn || this.hasTriggeredBy) ? 'left-connector' : ''; return index === 0 && (!this.isFirstColumn || this.hasTriggeredBy) ? 'left-connector' : '';
}, },
pipelineActionRequestComplete() { pipelineActionRequestComplete() {
this.$emit('refreshPipelineGraph'); this.$emit('refreshPipelineGraph');
}, },
...@@ -55,7 +49,8 @@ export default { ...@@ -55,7 +49,8 @@ export default {
<template> <template>
<li <li
:class="stageConnectorClass" :class="stageConnectorClass"
class="stage-column"> class="stage-column"
>
<div class="stage-name"> <div class="stage-name">
{{ title }} {{ title }}
</div> </div>
...@@ -83,7 +78,6 @@ export default { ...@@ -83,7 +78,6 @@ export default {
:group="group" :group="group"
@pipelineActionRequestComplete="pipelineActionRequestComplete" @pipelineActionRequestComplete="pipelineActionRequestComplete"
/> />
</li> </li>
</ul> </ul>
</div> </div>
......
...@@ -308,7 +308,8 @@ export default { ...@@ -308,7 +308,8 @@ export default {
<div <div
v-for="(stage, index) in pipeline.details.stages" v-for="(stage, index) in pipeline.details.stages"
:key="index" :key="index"
class="stage-container dropdown js-mini-pipeline-graph"> class="stage-container dropdown js-mini-pipeline-graph"
>
<pipeline-stage <pipeline-stage
:type="$options.pipelinesTable" :type="$options.pipelinesTable"
:stage="stage" :stage="stage"
......
...@@ -13,14 +13,13 @@ ...@@ -13,14 +13,13 @@
*/ */
import $ from 'jquery'; import $ from 'jquery';
import { GlLoadingIcon } from '@gitlab-org/gitlab-ui'; import { GlLoadingIcon, GlTooltipDirective } from '@gitlab-org/gitlab-ui';
import { __ } from '../../locale'; import { __ } from '../../locale';
import Flash from '../../flash'; import Flash from '../../flash';
import axios from '../../lib/utils/axios_utils'; import axios from '../../lib/utils/axios_utils';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import Icon from '../../vue_shared/components/icon.vue'; import Icon from '../../vue_shared/components/icon.vue';
import JobItem from './graph/job_item.vue'; import JobItem from './graph/job_item.vue';
import tooltip from '../../vue_shared/directives/tooltip';
import { PIPELINES_TABLE } from '../constants'; import { PIPELINES_TABLE } from '../constants';
export default { export default {
...@@ -31,7 +30,7 @@ export default { ...@@ -31,7 +30,7 @@ export default {
}, },
directives: { directives: {
tooltip, GlTooltip: GlTooltipDirective,
}, },
props: { props: {
...@@ -159,11 +158,10 @@ export default { ...@@ -159,11 +158,10 @@ export default {
<button <button
id="stageDropdown" id="stageDropdown"
ref="dropdown" ref="dropdown"
v-tooltip v-gl-tooltip.hover
:class="triggerButtonClass" :class="triggerButtonClass"
:title="stage.title" :title="stage.title"
class="mini-pipeline-graph-dropdown-toggle js-builds-dropdown-button" class="mini-pipeline-graph-dropdown-toggle js-builds-dropdown-button"
data-placement="top"
data-toggle="dropdown" data-toggle="dropdown"
data-display="static" data-display="static"
type="button" type="button"
......
---
title: Fix rendering of filter bar tokens for special values
merge_request: 22865
author: Heinrich Lee Yu
type: fixed
...@@ -53,17 +53,35 @@ To get started with the command line, please read through the ...@@ -53,17 +53,35 @@ To get started with the command line, please read through the
Use GitLab's [file finder](../../../workflow/file_finder.md) to search for files in a repository. Use GitLab's [file finder](../../../workflow/file_finder.md) to search for files in a repository.
### Supported markup languages and extensions
GitLab supports a number of markup languages (sometimes called [lightweight
markup languages](https://en.wikipedia.org/wiki/Lightweight_markup_language))
that you can use for the content of your files in a repository. They are mostly
used for documentation purposes.
Just pick the right extension for your files and GitLab will render them
according to the markup language.
| Markup language | Extensions |
| --------------- | ---------- |
| Plain text | `txt` |
| [Markdown](../../markdown.md) | `mdown`, `mkd`, `mkdn`, `md`, `markdown` |
| [reStructuredText](http://docutils.sourceforge.net/rst.html) | `rst` |
| [Asciidoc](https://asciidoctor.org/docs/what-is-asciidoc/) | `adoc`, `ad`, `asciidoc` |
| [Textile](https://txstyle.org/) | `textile` |
| [rdoc](http://rdoc.sourceforge.net/doc/index.html) | `rdoc` |
| [Orgmode](https://orgmode.org/) | `org` |
| [creole](http://www.wikicreole.org/) | `creole` |
| [Mediawiki](https://www.mediawiki.org/wiki/MediaWiki) | `wiki`, `mediawiki` |
### Repository README and index files ### Repository README and index files
When a `README` or `index` file is present in a repository, its contents will be When a `README` or `index` file is present in a repository, its contents will be
automatically pre-rendered by GitLab without opening it. automatically pre-rendered by GitLab without opening it.
They can either be plain text or have an extension of a supported markup language: They can either be plain text or have an extension of a
[supported markup language](#supported-markup-languages-and-extensions):
- Asciidoc: `README.adoc` or `index.adoc`
- Markdown: `README.md` or `index.md`
- reStructuredText: `README.rst` or `index.rst`
- Text: `README.txt` or `index.txt`
Some things to note about precedence: Some things to note about precedence:
...@@ -75,10 +93,6 @@ Some things to note about precedence: ...@@ -75,10 +93,6 @@ Some things to note about precedence:
precedence over `README.md`, and `README.rst` will take precedence over precedence over `README.md`, and `README.rst` will take precedence over
`README`. `README`.
NOTE: **Note:**
`index` files without an extension will not automatically pre-render. You'll
have to explicitly open them to see their contents.
### Jupyter Notebook files ### Jupyter Notebook files
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2508) in GitLab 9.1 > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2508) in GitLab 9.1
......
...@@ -107,4 +107,26 @@ describe('DiffFile', () => { ...@@ -107,4 +107,26 @@ describe('DiffFile', () => {
}); });
}); });
}); });
describe('watch collapsed', () => {
it('calls handleLoadCollapsedDiff if collapsed changed & file has no lines', done => {
spyOn(vm, 'handleLoadCollapsedDiff');
vm.file.highlightedDiffLines = undefined;
vm.file.parallelDiffLines = [];
vm.file.collapsed = true;
vm.$nextTick()
.then(() => {
vm.file.collapsed = false;
return vm.$nextTick();
})
.then(() => {
expect(vm.handleLoadCollapsedDiff).toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
});
}); });
...@@ -754,6 +754,50 @@ describe('Filtered Search Visual Tokens', () => { ...@@ -754,6 +754,50 @@ describe('Filtered Search Visual Tokens', () => {
expect(updateLabelTokenColorSpy.calls.count()).toBe(0); expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0); expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
}); });
it('does not update user token appearance for `none` filter', () => {
const { tokenNameElement } = findElements(authorToken);
const tokenName = tokenNameElement.innerText;
const tokenValue = 'none';
subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
});
it('does not update user token appearance for `any` filter', () => {
const { tokenNameElement } = findElements(authorToken);
const tokenName = tokenNameElement.innerText;
const tokenValue = 'any';
subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
});
it('does not update label token color for `none` filter', () => {
const { tokenNameElement } = findElements(bugLabelToken);
const tokenName = tokenNameElement.innerText;
const tokenValue = 'none';
subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
});
it('does not update label token color for `any` filter', () => {
const { tokenNameElement } = findElements(bugLabelToken);
const tokenName = tokenNameElement.innerText;
const tokenValue = 'any';
subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
});
}); });
describe('updateUserTokenAppearance', () => { describe('updateUserTokenAppearance', () => {
...@@ -763,19 +807,6 @@ describe('Filtered Search Visual Tokens', () => { ...@@ -763,19 +807,6 @@ describe('Filtered Search Visual Tokens', () => {
spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username)); spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username));
}); });
it('ignores special value "none"', done => {
usersCacheSpy = username => {
expect(username).toBe('none');
done.fail('Should not resolve "none"!');
};
const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
subject
.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, 'none')
.then(done)
.catch(done.fail);
});
it('ignores error if UsersCache throws', done => { it('ignores error if UsersCache throws', done => {
spyOn(window, 'Flash'); spyOn(window, 'Flash');
const dummyError = new Error('Earth rotated backwards'); const dummyError = new Error('Earth rotated backwards');
......
...@@ -140,14 +140,12 @@ describe('pipeline graph job item', () => { ...@@ -140,14 +140,12 @@ describe('pipeline graph job item', () => {
}); });
describe('tooltip placement', () => { describe('tooltip placement', () => {
const tooltipBoundary = 'a[data-boundary="viewport"]';
it('does not set tooltip boundary by default', () => { it('does not set tooltip boundary by default', () => {
component = mountComponent(JobComponent, { component = mountComponent(JobComponent, {
job: mockJob, job: mockJob,
}); });
expect(component.$el.querySelector(tooltipBoundary)).toBeNull(); expect(component.tooltipBoundary).toBeNull();
}); });
it('sets tooltip boundary to viewport for small dropdowns', () => { it('sets tooltip boundary to viewport for small dropdowns', () => {
...@@ -156,7 +154,7 @@ describe('pipeline graph job item', () => { ...@@ -156,7 +154,7 @@ describe('pipeline graph job item', () => {
dropdownLength: 1, dropdownLength: 1,
}); });
expect(component.$el.querySelector(tooltipBoundary)).not.toBeNull(); expect(component.tooltipBoundary).toEqual('viewport');
}); });
it('does not set tooltip boundary for large lists', () => { it('does not set tooltip boundary for large lists', () => {
...@@ -165,7 +163,7 @@ describe('pipeline graph job item', () => { ...@@ -165,7 +163,7 @@ describe('pipeline graph job item', () => {
dropdownLength: 7, dropdownLength: 7,
}); });
expect(component.$el.querySelector(tooltipBoundary)).toBeNull(); expect(component.tooltipBoundary).toBeNull();
}); });
}); });
......
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