Read about our upcoming Code of Conduct on this issue

Commit 758a3a65 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent d821732f4cb1
......@@ -106,6 +106,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- Remove "creations" in gitlab_subscription_histories on gitlab.com. !22278
## 12.6.7
- No changes.
## 12.6.6
- No changes.
......
......@@ -455,7 +455,7 @@ group :ed25519 do
end
# Gitaly GRPC protocol definitions
gem 'gitaly', '~> 1.85.0'
gem 'gitaly', '~> 1.86.0'
gem 'grpc', '~> 1.24.0'
......
......@@ -375,7 +375,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
git (1.5.0)
gitaly (1.85.0)
gitaly (1.86.0)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab-chronic (0.10.5)
......@@ -1230,7 +1230,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
gitaly (~> 1.85.0)
gitaly (~> 1.86.0)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-labkit (= 0.9.1)
......
<script>
import { mapActions } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui';
import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
GlAlert,
GlLoadingIcon,
},
props: {
......@@ -17,9 +18,14 @@ export default {
isLoading: false,
};
},
computed: {
canDismiss() {
return !this.message.action;
},
},
methods: {
...mapActions(['setErrorMessage']),
clickAction() {
doAction() {
if (this.isLoading) return;
this.isLoading = true;
......@@ -33,28 +39,23 @@ export default {
this.isLoading = false;
});
},
clickFlash() {
if (!this.message.action) {
this.setErrorMessage(null);
}
dismiss() {
this.setErrorMessage(null);
},
},
};
</script>
<template>
<div class="flash-container flash-container-page" @click="clickFlash">
<div class="flash-alert" data-qa-selector="flash_alert">
<span v-html="message.text"> </span>
<button
v-if="message.action"
type="button"
class="flash-action text-white p-0 border-top-0 border-right-0 border-left-0 bg-transparent"
@click.stop.prevent="clickAction"
>
{{ message.actionText }}
<gl-loading-icon v-show="isLoading" inline />
</button>
</div>
</div>
<gl-alert
data-qa-selector="flash_alert"
variant="danger"
:dismissible="canDismiss"
:primary-button-text="message.actionText"
@dismiss="dismiss"
@primaryAction="doAction"
>
<span v-html="message.text"></span>
<gl-loading-icon v-show="isLoading" inline class="vertical-align-middle ml-1" />
</gl-alert>
</template>
<script>
import _ from 'underscore';
import { GlLoadingIcon } from '@gitlab/ui';
import StageColumnComponent from './stage_column_component.vue';
import GraphMixin from '../../mixins/graph_component_mixin';
......@@ -70,7 +69,7 @@ export default {
expandedTriggeredBy() {
return (
this.pipeline.triggered_by &&
_.isArray(this.pipeline.triggered_by) &&
Array.isArray(this.pipeline.triggered_by) &&
this.pipeline.triggered_by.find(el => el.isExpanded)
);
},
......
<script>
import _ from 'underscore';
import { isEmpty, escape as esc } from 'lodash';
import stageColumnMixin from '../../mixins/stage_column_mixin';
import JobItem from './job_item.vue';
import JobGroupDropdown from './job_group_dropdown.vue';
......@@ -39,12 +39,12 @@ export default {
},
computed: {
hasAction() {
return !_.isEmpty(this.action);
return !isEmpty(this.action);
},
},
methods: {
groupId(group) {
return `ci-badge-${_.escape(group.name)}`;
return `ci-badge-${esc(group.name)}`;
},
pipelineActionRequestComplete() {
this.$emit('refreshPipelineGraph');
......
<script>
import _ from 'underscore';
import { isEmpty } from 'lodash';
import { GlLink } from '@gitlab/ui';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
......@@ -43,7 +43,7 @@ export default {
);
},
hasRef() {
return !_.isEmpty(this.pipeline.ref);
return !isEmpty(this.pipeline.ref);
},
},
methods: {
......
<script>
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import _ from 'underscore';
import { escape } from 'lodash';
import { __, sprintf } from '~/locale';
import popover from '~/vue_shared/directives/popover';
const popoverTitle = sprintf(
_.escape(
escape(
__(
`This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}`,
),
......@@ -49,7 +49,7 @@ export default {
href="${this.autoDevopsHelpPath}"
target="_blank"
rel="noopener noreferrer nofollow">
${_.escape(__('Learn more about Auto DevOps'))}
${escape(__('Learn more about Auto DevOps'))}
</a>`,
};
},
......
<script>
import _ from 'underscore';
import { isEqual } from 'lodash';
import { __, sprintf, s__ } from '../../locale';
import createFlash from '../../flash';
import PipelinesService from '../services/pipelines_service';
......@@ -218,7 +218,7 @@ export default {
successCallback(resp) {
// Because we are polling & the user is interacting verify if the response received
// matches the last request made
if (_.isEqual(resp.config.params, this.requestData)) {
if (isEqual(resp.config.params, this.requestData)) {
this.store.storeCount(resp.data.count);
this.store.storePagination(resp.headers);
this.setCommonData(resp.data.pipelines);
......
import _ from 'underscore';
import { escape } from 'lodash';
export default {
props: {
......@@ -18,7 +18,7 @@ export default {
},
methods: {
capitalizeStageName(name) {
const escapedName = _.escape(name);
const escapedName = escape(name);
return escapedName.charAt(0).toUpperCase() + escapedName.slice(1);
},
isFirstColumn(index) {
......
import Vue from 'vue';
import _ from 'underscore';
export default class PipelineStore {
constructor() {
......@@ -61,7 +60,7 @@ export default class PipelineStore {
Vue.set(newPipeline, 'isLoading', false);
if (newPipeline.triggered_by) {
if (!_.isArray(newPipeline.triggered_by)) {
if (!Array.isArray(newPipeline.triggered_by)) {
Object.assign(newPipeline, { triggered_by: [newPipeline.triggered_by] });
}
this.parseTriggeredByPipelines(oldPipeline, newPipeline.triggered_by[0]);
......
<script>
import _ from 'underscore';
import { isString } from 'lodash';
import { mapState, mapActions, mapGetters } from 'vuex';
import PodBox from './pod_box.vue';
import Url from './url.vue';
......@@ -42,7 +42,7 @@ export default {
return this.func.name;
},
description() {
return _.isString(this.func.description) ? this.func.description : '';
return isString(this.func.description) ? this.func.description : '';
},
funcUrl() {
return this.func.url;
......
<script>
import _ from 'underscore';
import { isString } from 'lodash';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import Url from './url.vue';
import { visitUrl } from '~/lib/utils/url_utility';
......@@ -20,7 +20,7 @@ export default {
return this.func.name;
},
description() {
if (!_.isString(this.func.description)) {
if (!isString(this.func.description)) {
return '';
}
......
......@@ -5,6 +5,7 @@ import { __, sprintf } from '~/locale';
import { convertToFixedRange, isEqualTimeRanges, findTimeRange } from '~/lib/utils/datetime_range';
import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
import DateTimePickerInput from './date_time_picker_input.vue';
import {
defaultTimeRanges,
......@@ -24,6 +25,7 @@ const events = {
export default {
components: {
Icon,
TooltipOnTruncate,
DateTimePickerInput,
GlFormGroup,
GlButton,
......@@ -149,61 +151,68 @@ export default {
};
</script>
<template>
<gl-dropdown
:text="timeWindowText"
class="date-time-picker"
menu-class="date-time-picker-menu"
v-bind="$attrs"
toggle-class="w-100 text-truncate"
<tooltip-on-truncate
:title="timeWindowText"
:truncate-target="elem => elem.querySelector('.date-time-picker-toggle')"
placement="top"
class="d-inline-block"
>
<div class="d-flex justify-content-between gl-p-2">
<gl-form-group
:label="__('Custom range')"
label-for="custom-from-time"
label-class="gl-pb-1"
class="custom-time-range-form-group col-md-7 gl-pl-1 gl-pr-0 m-0"
>
<div class="gl-pt-2">
<date-time-picker-input
id="custom-time-from"
v-model="startInput"
:label="__('From')"
:state="startInputValid"
/>
<date-time-picker-input
id="custom-time-to"
v-model="endInput"
:label="__('To')"
:state="endInputValid"
/>
</div>
<gl-form-group>
<gl-button @click="closeDropdown">{{ __('Cancel') }}</gl-button>
<gl-button variant="success" :disabled="!isValid" @click="setFixedRange()">
{{ __('Apply') }}
</gl-button>
<gl-dropdown
:text="timeWindowText"
v-bind="$attrs"
class="date-time-picker w-100"
menu-class="date-time-picker-menu"
toggle-class="date-time-picker-toggle text-truncate"
>
<div class="d-flex justify-content-between gl-p-2">
<gl-form-group
:label="__('Custom range')"
label-for="custom-from-time"
label-class="gl-pb-1"
class="custom-time-range-form-group col-md-7 gl-pl-1 gl-pr-0 m-0"
>
<div class="gl-pt-2">
<date-time-picker-input
id="custom-time-from"
v-model="startInput"
:label="__('From')"
:state="startInputValid"
/>
<date-time-picker-input
id="custom-time-to"
v-model="endInput"
:label="__('To')"
:state="endInputValid"
/>
</div>
<gl-form-group>
<gl-button @click="closeDropdown">{{ __('Cancel') }}</gl-button>
<gl-button variant="success" :disabled="!isValid" @click="setFixedRange()">
{{ __('Apply') }}
</gl-button>
</gl-form-group>
</gl-form-group>
</gl-form-group>
<gl-form-group label-for="group-id-dropdown" class="col-md-5 gl-pl-1 gl-pr-1 m-0">
<template #label>
<span class="gl-pl-5">{{ __('Quick range') }}</span>
</template>
<gl-form-group label-for="group-id-dropdown" class="col-md-5 gl-pl-1 gl-pr-1 m-0">
<template #label>
<span class="gl-pl-5">{{ __('Quick range') }}</span>
</template>
<gl-dropdown-item
v-for="(option, index) in options"
:key="index"
:active="isOptionActive(option)"
active-class="active"
@click="setQuickRange(option)"
>
<icon
name="mobile-issue-close"
class="align-bottom"
:class="{ invisible: !isOptionActive(option) }"
/>
{{ option.label }}
</gl-dropdown-item>
</gl-form-group>
</div>
</gl-dropdown>
<gl-dropdown-item
v-for="(option, index) in options"
:key="index"
:active="isOptionActive(option)"
active-class="active"
@click="setQuickRange(option)"
>
<icon
name="mobile-issue-close"
class="align-bottom"
:class="{ invisible: !isOptionActive(option) }"
/>
{{ option.label }}
</gl-dropdown-item>
</gl-form-group>
</div>
</gl-dropdown>
</tooltip-on-truncate>
</template>
<script>
import _ from 'underscore';
import { isFunction } from 'lodash';
import tooltip from '../directives/tooltip';
export default {
......@@ -28,16 +28,18 @@ export default {
showTooltip: false,
};
},
watch: {
title() {
// Wait on $nextTick in case of slot width changes
this.$nextTick(this.updateTooltip);
},
},
mounted() {
const target = this.selectTarget();
if (target && target.scrollWidth > target.offsetWidth) {
this.showTooltip = true;
}
this.updateTooltip();
},
methods: {
selectTarget() {
if (_.isFunction(this.truncateTarget)) {
if (isFunction(this.truncateTarget)) {
return this.truncateTarget(this.$el);
} else if (this.truncateTarget === 'child') {
return this.$el.childNodes[0];
......@@ -45,6 +47,10 @@ export default {
return this.$el;
},
updateTooltip() {
const target = this.selectTarget();
this.showTooltip = Boolean(target && target.scrollWidth > target.offsetWidth);
},
},
};
</script>
......
......@@ -901,7 +901,9 @@ def import_url=(value)
if Gitlab::UrlSanitizer.valid?(value)
import_url = Gitlab::UrlSanitizer.new(value)
super(import_url.sanitized_url)
create_or_update_import_data(credentials: import_url.credentials)
credentials = import_url.credentials.to_h.transform_values { |value| CGI.unescape(value.to_s) }
create_or_update_import_data(credentials: credentials)
else
super(value)
end
......
......@@ -134,15 +134,6 @@ def commits_by(oids:)
end
end
# the opts are:
# - :path
# - :limit
# - :offset
# - :skip_merges
# - :after
# - :before
# - :all
# - :first_parent
def commits(ref = nil, opts = {})
options = {
repo: raw_repository,
......@@ -155,7 +146,8 @@ def commits(ref = nil, opts = {})
after: opts[:after],
before: opts[:before],
all: !!opts[:all],
first_parent: !!opts[:first_parent]
first_parent: !!opts[:first_parent],
order: opts[:order]
}
commits = Gitlab::Git::Commit.where(options)
......
......@@ -19,8 +19,10 @@ class RefreshAuthorizedProjectsService
LEASE_TIMEOUT = 1.minute.to_i
# user - The User for which to refresh the authorized projects.
def initialize(user)
def initialize(user, incorrect_auth_found_callback: nil, missing_auth_found_callback: nil)
@user = user
@incorrect_auth_found_callback = incorrect_auth_found_callback
@missing_auth_found_callback = missing_auth_found_callback
# We need an up to date User object that has access to all relations that
# may have been created earlier. The only way to ensure this is to reload
......@@ -55,6 +57,10 @@ def execute_without_lease
# rows not in the new list or with a different access level should be
# removed.
if !fresh[project_id] || fresh[project_id] != row.access_level
if incorrect_auth_found_callback
incorrect_auth_found_callback.call(project_id, row.access_level)
end
array << row.project_id
end
end
......@@ -63,6 +69,10 @@ def execute_without_lease
# rows not in the old list or with a different access level should be
# added.
if !current[project_id] || current[project_id].access_level != level
if missing_auth_found_callback
missing_auth_found_callback.call(project_id, level)
end
array << [user.id, project_id, level]
end
end
......@@ -104,5 +114,9 @@ def current_authorizations
def fresh_authorizations
Gitlab::ProjectAuthorizations.new(user).calculate
end
private
attr_reader :incorrect_auth_found_callback, :missing_auth_found_callback
end
end
---
title: Add tooltip when dates in date picker are too long
merge_request: 24664
author:
type: added
---
title: 'API: Ability to list commits in order (--topo-order)'
merge_request: 24702
author:
type: added
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