提交 03a52173 编写于 作者: G GitLab Bot

Add latest changes from gitlab-org/gitlab@master

上级 e28b754d
/* eslint-disable @gitlab/require-i18n-strings */
import { __ } from '~/locale';
export const ANY_AUTHOR = 'Any';
const DEFAULT_LABEL_NO_LABEL = { value: 'No label', text: __('No label') };
export const DEFAULT_LABEL_NONE = { value: 'None', text: __('None') };
export const DEFAULT_LABEL_ANY = { value: 'Any', text: __('Any') };
......
......@@ -11,10 +11,9 @@ import { debounce } from 'lodash';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import { __ } from '~/locale';
import { ANY_AUTHOR, DEBOUNCE_DELAY } from '../constants';
import { DEFAULT_LABEL_ANY, DEBOUNCE_DELAY } from '../constants';
export default {
anyAuthor: ANY_AUTHOR,
components: {
GlFilteredSearchToken,
GlAvatar,
......@@ -35,6 +34,7 @@ export default {
data() {
return {
authors: this.config.initialAuthors || [],
defaultAuthors: this.config.defaultAuthors || [DEFAULT_LABEL_ANY],
loading: true,
};
},
......@@ -99,10 +99,14 @@ export default {
<span>{{ activeAuthor ? activeAuthor.name : inputValue }}</span>
</template>
<template #suggestions>
<gl-filtered-search-suggestion :value="$options.anyAuthor">
{{ __('Any') }}
<gl-filtered-search-suggestion
v-for="author in defaultAuthors"
:key="author.value"
:value="author.value"
>
{{ author.text }}
</gl-filtered-search-suggestion>
<gl-deprecated-dropdown-divider />
<gl-deprecated-dropdown-divider v-if="defaultAuthors.length" />
<gl-loading-icon v-if="loading" />
<template v-else>
<gl-filtered-search-suggestion
......
......@@ -112,7 +112,7 @@ export default {
>
{{ label.text }}
</gl-filtered-search-suggestion>
<gl-dropdown-divider />
<gl-dropdown-divider v-if="defaultLabels.length" />
<gl-loading-icon v-if="loading" />
<template v-else>
<gl-filtered-search-suggestion v-for="label in labels" :key="label.id" :value="label.title">
......
......@@ -95,7 +95,7 @@ export default {
>
{{ milestone.text }}
</gl-filtered-search-suggestion>
<gl-dropdown-divider />
<gl-dropdown-divider v-if="defaultMilestones.length" />
<gl-loading-icon v-if="loading" />
<template v-else>
<gl-filtered-search-suggestion
......
......@@ -36,8 +36,8 @@ class Iteration < ApplicationRecord
.where('due_date is NULL or due_date >= ?', start_date)
end
scope :start_date_passed, -> { where('start_date <= ?', Date.current).where('due_date > ?', Date.current) }
scope :due_date_passed, -> { where('due_date <= ?', Date.current) }
scope :start_date_passed, -> { where('start_date <= ?', Date.current).where('due_date >= ?', Date.current) }
scope :due_date_passed, -> { where('due_date < ?', Date.current) }
state_machine :state_enum, initial: :upcoming do
event :start do
......
- page_description brand_title unless page_description
-# Needs a redirect on the client side since it's using an anchor to distuingish
-# Needs a redirect on the client side since it's using an anchor to distinguish
-# between sign in and registration. We need to inline the JS to not render
-# anything from this page beforehand.
-# Part of an experiment to build a new sign up flow. Will be removed again with
......
---
title: Update lodash to 4.17.20
merge_request: 41036
author: Takuya Noguchi
type: security
......@@ -720,6 +720,24 @@ sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/s
sudo cp /opt/gitlab/embedded/ssl/certs/cacert.pem /var/opt/gitlab/gitlab-rails/shared/pages/etc/ssl/ca-bundle.pem
```
### 502 error when connecting to GitLab Pages proxy when server does not listen over IPv6
In some cases, NGINX might default to using IPv6 to connect to the GitLab Pages
service even when the server does not listen over IPv6. You can identify when
this is happening if you see something similar to the log entry below in the
`gitlab_pages_error.log`:
```plaintext
2020/02/24 16:32:05 [error] 112654#0: *4982804 connect() failed (111: Connection refused) while connecting to upstream, client: 123.123.123.123, server: ~^(?<group>.*)\.pages\.example\.com$, request: "GET /-/group/project/-/jobs/1234/artifacts/artifact.txt HTTP/1.1", upstream: "http://[::1]:8090//-/group/project/-/jobs/1234/artifacts/artifact.txt", host: "group.example.com"
```
To resolve this, set an explicit IP and port for the GitLab Pages `listen_proxy` setting
to define the explicit address that the GitLab Pages daemon should listen on:
```ruby
gitlab_pages['listen_proxy'] = '127.0.0.1:8090'
```
### 404 error after transferring project to a different group or user
If you encounter a `404 Not Found` error a Pages site after transferring a project to
......
import { mount } from '@vue/test-utils';
import { GlFilteredSearchToken, GlFilteredSearchTokenSegment } from '@gitlab/ui';
import {
GlFilteredSearchToken,
GlFilteredSearchTokenSegment,
GlFilteredSearchSuggestion,
GlNewDropdownDivider as GlDropdownDivider,
} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import {
DEFAULT_LABEL_NONE,
DEFAULT_LABEL_ANY,
} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import { mockAuthorToken, mockAuthors } from '../mock_data';
jest.mock('~/flash');
const createComponent = ({ config = mockAuthorToken, value = { data: '' }, active = false } = {}) =>
mount(AuthorToken, {
const defaultStubs = {
Portal: true,
GlFilteredSearchSuggestionList: {
template: '<div></div>',
methods: {
getValue: () => '=',
},
},
};
function createComponent(options = {}) {
const {
config = mockAuthorToken,
value = { data: '' },
active = false,
stubs = defaultStubs,
} = options;
return mount(AuthorToken, {
propsData: {
config,
value,
......@@ -22,16 +46,9 @@ const createComponent = ({ config = mockAuthorToken, value = { data: '' }, activ
portalName: 'fake target',
alignSuggestions: function fakeAlignSuggestions() {},
},
stubs: {
Portal: true,
GlFilteredSearchSuggestionList: {
template: '<div></div>',
methods: {
getValue: () => '=',
},
},
},
stubs,
});
}
describe('AuthorToken', () => {
let mock;
......@@ -139,5 +156,57 @@ describe('AuthorToken', () => {
expect(tokenSegments.at(2).text()).toBe(mockAuthors[0].name); // "Administrator"
});
});
it('renders provided defaultAuthors as suggestions', async () => {
const defaultAuthors = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
wrapper = createComponent({
active: true,
config: { ...mockAuthorToken, defaultAuthors },
stubs: { Portal: true },
});
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(defaultAuthors.length);
defaultAuthors.forEach((label, index) => {
expect(suggestions.at(index).text()).toBe(label.text);
});
});
it('does not render divider when no defaultAuthors', async () => {
wrapper = createComponent({
active: true,
config: { ...mockAuthorToken, defaultAuthors: [] },
stubs: { Portal: true },
});
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
expect(wrapper.contains(GlDropdownDivider)).toBe(false);
});
it('renders `DEFAULT_LABEL_ANY` as default suggestions', async () => {
wrapper = createComponent({
active: true,
config: { ...mockAuthorToken },
stubs: { Portal: true },
});
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
expect(suggestions).toHaveLength(1);
expect(suggestions.at(0).text()).toBe(DEFAULT_LABEL_ANY.text);
});
});
});
......@@ -3,6 +3,7 @@ import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlFilteredSearchTokenSegment,
GlNewDropdownDivider as GlDropdownDivider,
} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -33,13 +34,14 @@ const defaultStubs = {
},
};
const createComponent = ({
config = mockLabelToken,
value = { data: '' },
active = false,
stubs = defaultStubs,
} = {}) =>
mount(LabelToken, {
function createComponent(options = {}) {
const {
config = mockLabelToken,
value = { data: '' },
active = false,
stubs = defaultStubs,
} = options;
return mount(LabelToken, {
propsData: {
config,
value,
......@@ -51,6 +53,7 @@ const createComponent = ({
},
stubs,
});
}
describe('LabelToken', () => {
let mock;
......@@ -204,6 +207,21 @@ describe('LabelToken', () => {
});
});
it('does not render divider when no defaultLabels', async () => {
wrapper = createComponent({
active: true,
config: { ...mockLabelToken, defaultLabels: [] },
stubs: { Portal: true },
});
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
expect(wrapper.contains(GlDropdownDivider)).toBe(false);
});
it('renders `DEFAULT_LABELS` as default suggestions', async () => {
wrapper = createComponent({
active: true,
......
......@@ -3,6 +3,7 @@ import {
GlFilteredSearchToken,
GlFilteredSearchSuggestion,
GlFilteredSearchTokenSegment,
GlNewDropdownDivider as GlDropdownDivider,
} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
......@@ -31,13 +32,14 @@ const defaultStubs = {
},
};
const createComponent = ({
config = mockMilestoneToken,
value = { data: '' },
active = false,
stubs = defaultStubs,
} = {}) =>
mount(MilestoneToken, {
function createComponent(options = {}) {
const {
config = mockMilestoneToken,
value = { data: '' },
active = false,
stubs = defaultStubs,
} = options;
return mount(MilestoneToken, {
propsData: {
config,
value,
......@@ -49,6 +51,7 @@ const createComponent = ({
},
stubs,
});
}
describe('MilestoneToken', () => {
let mock;
......@@ -176,6 +179,21 @@ describe('MilestoneToken', () => {
});
});
it('does not render divider when no defaultMilestones', async () => {
wrapper = createComponent({
active: true,
config: { ...mockMilestoneToken, defaultMilestones: [] },
stubs: { Portal: true },
});
const tokenSegments = wrapper.findAll(GlFilteredSearchTokenSegment);
const suggestionsSegment = tokenSegments.at(2);
suggestionsSegment.vm.$emit('activate');
await wrapper.vm.$nextTick();
expect(wrapper.contains(GlFilteredSearchSuggestion)).toBe(false);
expect(wrapper.contains(GlDropdownDivider)).toBe(false);
});
it('renders `DEFAULT_MILESTONES` as default suggestions', async () => {
wrapper = createComponent({
active: true,
......
......@@ -7744,10 +7744,10 @@ lodash.values@^4.3.0:
resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347"
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@~4.17.10:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@~4.17.10:
version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
log-symbols@^2.1.0, log-symbols@^2.2.0:
version "2.2.0"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册