Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-22 03:08:07 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-22 03:08:07 +0300
commit21539fe9ab9a7a9604bb667b78b08854b4976f7b (patch)
tree82fb2be49aaaace5057d1e8e208ad12a422a7bbb /app
parente7bc93852d0ce48c490a780b6a1adc6cc36dd342 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/frequent_items/index.js76
-rw-r--r--app/assets/javascripts/main.js3
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue11
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue5
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue2
-rw-r--r--app/graphql/mutations/concerns/mutations/resolves_issuable.rb9
-rw-r--r--app/graphql/resolvers/concerns/resolves_merge_requests.rb50
-rw-r--r--app/graphql/resolvers/merge_request_resolver.rb18
-rw-r--r--app/graphql/resolvers/merge_requests_resolver.rb52
-rw-r--r--app/graphql/types/merge_request_type.rb8
-rw-r--r--app/graphql/types/permission_types/merge_request.rb12
-rw-r--r--app/services/releases/create_service.rb12
-rw-r--r--app/views/shared/_promo.html.haml6
13 files changed, 180 insertions, 84 deletions
diff --git a/app/assets/javascripts/frequent_items/index.js b/app/assets/javascripts/frequent_items/index.js
index 6263acbab8e..c074f173776 100644
--- a/app/assets/javascripts/frequent_items/index.js
+++ b/app/assets/javascripts/frequent_items/index.js
@@ -1,8 +1,7 @@
import $ from 'jquery';
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
-import eventHub from '~/frequent_items/event_hub';
-import frequentItems from './components/app.vue';
+import eventHub from './event_hub';
Vue.use(Translate);
@@ -17,7 +16,7 @@ const frequentItemDropdowns = [
},
];
-const initFrequentItemDropdowns = () => {
+export default function initFrequentItemDropdowns() {
frequentItemDropdowns.forEach(dropdown => {
const { namespace, key } = dropdown;
const el = document.getElementById(`js-${namespace}-dropdown`);
@@ -29,45 +28,40 @@ const initFrequentItemDropdowns = () => {
return;
}
- $(navEl).on('shown.bs.dropdown', () => {
- eventHub.$emit(`${namespace}-dropdownOpen`);
- });
+ $(navEl).on('shown.bs.dropdown', () =>
+ import('./components/app.vue').then(({ default: FrequentItems }) => {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ data() {
+ const { dataset } = this.$options.el;
+ const item = {
+ id: Number(dataset[`${key}Id`]),
+ name: dataset[`${key}Name`],
+ namespace: dataset[`${key}Namespace`],
+ webUrl: dataset[`${key}WebUrl`],
+ avatarUrl: dataset[`${key}AvatarUrl`] || null,
+ lastAccessedOn: Date.now(),
+ };
- // eslint-disable-next-line no-new
- new Vue({
- el,
- components: {
- frequentItems,
- },
- data() {
- const { dataset } = this.$options.el;
- const item = {
- id: Number(dataset[`${key}Id`]),
- name: dataset[`${key}Name`],
- namespace: dataset[`${key}Namespace`],
- webUrl: dataset[`${key}WebUrl`],
- avatarUrl: dataset[`${key}AvatarUrl`] || null,
- lastAccessedOn: Date.now(),
- };
-
- return {
- currentUserName: dataset.userName,
- currentItem: item,
- };
- },
- render(createElement) {
- return createElement('frequent-items', {
- props: {
- namespace,
- currentUserName: this.currentUserName,
- currentItem: this.currentItem,
+ return {
+ currentUserName: dataset.userName,
+ currentItem: item,
+ };
+ },
+ render(createElement) {
+ return createElement(FrequentItems, {
+ props: {
+ namespace,
+ currentUserName: this.currentUserName,
+ currentItem: this.currentItem,
+ },
+ });
},
});
- },
- });
- });
-};
-document.addEventListener('DOMContentLoaded', () => {
- requestIdleCallback(initFrequentItemDropdowns);
-});
+ eventHub.$emit(`${namespace}-dropdownOpen`);
+ }),
+ );
+ });
+}
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 713f57a2b27..dbe445b374d 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -28,7 +28,7 @@ import initLayoutNav from './layout_nav';
import './feature_highlight/feature_highlight_options';
import LazyLoader from './lazy_loader';
import initLogoAnimation from './logo';
-import './frequent_items';
+import initFrequentItemDropdowns from './frequent_items';
import initBreadcrumbs from './breadcrumb';
import initUsagePingConsent from './usage_ping_consent';
import initPerformanceBar from './performance_bar';
@@ -107,6 +107,7 @@ function deferredInitialisation() {
initUsagePingConsent();
initUserPopovers();
initBroadcastNotifications();
+ initFrequentItemDropdowns();
const recoverySettingsCallout = document.querySelector('.js-recovery-settings-callout');
PersistentUserCallout.factory(recoverySettingsCallout);
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index e1a0e2df0e0..ef24dbfb6ce 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -39,6 +39,11 @@ export default {
metricDetails() {
return this.currentRequest.details[this.metric];
},
+ metricDetailsLabel() {
+ return this.metricDetails.duration
+ ? `${this.metricDetails.duration} / ${this.metricDetails.calls}`
+ : this.metricDetails.calls;
+ },
detailsList() {
return this.metricDetails.details;
},
@@ -68,7 +73,7 @@ export default {
type="button"
data-toggle="modal"
>
- {{ metricDetails.duration }} / {{ metricDetails.calls }}
+ {{ metricDetailsLabel }}
</button>
<gl-modal
:id="`modal-peek-${metric}-details`"
@@ -80,7 +85,9 @@ export default {
<template v-if="detailsList.length">
<tr v-for="(item, index) in detailsList" :key="index">
<td>
- <span>{{ sprintf(__('%{duration}ms'), { duration: item.duration }) }}</span>
+ <span v-if="item.duration">{{
+ sprintf(__('%{duration}ms'), { duration: item.duration })
+ }}</span>
</td>
<td>
<div class="js-toggle-container">
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 1df5562e1b6..41147ccaea8 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -38,6 +38,11 @@ export default {
keys: ['sql'],
},
{
+ metric: 'bullet',
+ header: s__('PerformanceBar|Bullet notifications'),
+ keys: ['notification'],
+ },
+ {
metric: 'gitaly',
header: s__('PerformanceBar|Gitaly calls'),
keys: ['feature', 'request'],
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index 58045b57d80..adb0e69b786 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -109,7 +109,7 @@ export default {
<evidence-block v-if="hasEvidence && shouldShowEvidence" :release="release" />
<div ref="gfm-content" class="card-text prepend-top-default">
- <div v-html="release.descriptionHtml"></div>
+ <div class="md" v-html="release.descriptionHtml"></div>
</div>
</div>
diff --git a/app/graphql/mutations/concerns/mutations/resolves_issuable.rb b/app/graphql/mutations/concerns/mutations/resolves_issuable.rb
index d63cc27a450..f3ed3565b03 100644
--- a/app/graphql/mutations/concerns/mutations/resolves_issuable.rb
+++ b/app/graphql/mutations/concerns/mutations/resolves_issuable.rb
@@ -7,8 +7,15 @@ module Mutations
def resolve_issuable(type:, parent_path:, iid:)
parent = resolve_issuable_parent(type, parent_path)
+ key = type == :merge_request ? :iids : :iid
+ args = { key => iid.to_s }
- issuable_resolver(type, parent, context).resolve(iid: iid.to_s)
+ resolver = issuable_resolver(type, parent, context)
+ ready, early_return = resolver.ready?(**args)
+
+ return early_return unless ready
+
+ resolver.resolve(**args)
end
private
diff --git a/app/graphql/resolvers/concerns/resolves_merge_requests.rb b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
new file mode 100644
index 00000000000..779ff0b50d4
--- /dev/null
+++ b/app/graphql/resolvers/concerns/resolves_merge_requests.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+# Mixin for resolving merge requests. All arguments must be in forms
+# that `MergeRequestsFinder` can handle, so you may need to use aliasing.
+module ResolvesMergeRequests
+ extend ActiveSupport::Concern
+
+ included do
+ type Types::MergeRequestType, null: true
+ end
+
+ def resolve(**args)
+ args[:iids] = Array.wrap(args[:iids]) if args[:iids]
+ args.compact!
+
+ if args.keys == [:iids]
+ batch_load_merge_requests(args[:iids])
+ else
+ args[:project_id] = project.id
+
+ MergeRequestsFinder.new(current_user, args).execute
+ end.then(&(single? ? :first : :itself))
+ end
+
+ def ready?(**args)
+ return early_return if no_results_possible?(args)
+
+ super
+ end
+
+ def early_return
+ [false, single? ? nil : MergeRequest.none]
+ end
+
+ private
+
+ def batch_load_merge_requests(iids)
+ iids.map { |iid| batch_load(iid) }.select(&:itself) # .compact doesn't work on BatchLoader
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def batch_load(iid)
+ BatchLoader::GraphQL.for(iid.to_s).batch(key: project) do |iids, loader, args|
+ args[:key].merge_requests.where(iid: iids).each do |mr|
+ loader.call(mr.iid.to_s, mr)
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+end
diff --git a/app/graphql/resolvers/merge_request_resolver.rb b/app/graphql/resolvers/merge_request_resolver.rb
new file mode 100644
index 00000000000..a47a128ea32
--- /dev/null
+++ b/app/graphql/resolvers/merge_request_resolver.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class MergeRequestResolver < BaseResolver.single
+ include ResolvesMergeRequests
+
+ alias_method :project, :synchronized_object
+
+ argument :iid, GraphQL::STRING_TYPE,
+ required: true,
+ as: :iids,
+ description: 'IID of the merge request, for example `1`'
+
+ def no_results_possible?(args)
+ project.nil?
+ end
+ end
+end
diff --git a/app/graphql/resolvers/merge_requests_resolver.rb b/app/graphql/resolvers/merge_requests_resolver.rb
index 25121dce005..44fc4e17cd4 100644
--- a/app/graphql/resolvers/merge_requests_resolver.rb
+++ b/app/graphql/resolvers/merge_requests_resolver.rb
@@ -2,47 +2,39 @@
module Resolvers
class MergeRequestsResolver < BaseResolver
- argument :iid, GraphQL::STRING_TYPE,
- required: false,
- description: 'IID of the merge request, for example `1`'
+ include ResolvesMergeRequests
+
+ alias_method :project, :synchronized_object
argument :iids, [GraphQL::STRING_TYPE],
required: false,
description: 'Array of IIDs of merge requests, for example `[1, 2]`'
- type Types::MergeRequestType, null: true
-
- alias_method :project, :object
+ argument :source_branches, [GraphQL::STRING_TYPE],
+ required: false,
+ as: :source_branch,
+ description: 'Array of source branch names. All resolved merge requests will have one of these branches as their source.'
- def resolve(**args)
- project = object.respond_to?(:sync) ? object.sync : object
- return MergeRequest.none if project.nil?
+ argument :target_branches, [GraphQL::STRING_TYPE],
+ required: false,
+ as: :target_branch,
+ description: 'Array of target branch names. All resolved merge requests will have one of these branches as their target.'
- args[:iids] ||= [args[:iid]].compact
+ argument :state, ::Types::MergeRequestStateEnum,
+ required: false,
+ description: 'A merge request state. If provided, all resolved merge requests will have this state.'
- if args[:iids].any?
- batch_load_merge_requests(args[:iids])
- else
- args[:project_id] = project.id
+ argument :labels, [GraphQL::STRING_TYPE],
+ required: false,
+ as: :label_name,
+ description: 'Array of label names. All resolved merge requests will have all of these labels.'
- MergeRequestsFinder.new(context[:current_user], args).execute
- end
+ def self.single
+ ::Resolvers::MergeRequestResolver
end
- def batch_load_merge_requests(iids)
- iids.map { |iid| batch_load(iid) }.select(&:itself) # .compact doesn't work on BatchLoader
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def batch_load(iid)
- BatchLoader::GraphQL.for(iid.to_s).batch(key: project) do |iids, loader, args|
- arg_key = args[:key].respond_to?(:sync) ? args[:key].sync : args[:key]
-
- arg_key.merge_requests.where(iid: iids).each do |mr|
- loader.call(mr.iid.to_s, mr)
- end
- end
+ def no_results_possible?(args)
+ project.nil? || args.values.any? { |v| v.is_a?(Array) && v.empty? }
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index cd4c6b4d46a..6ac385a8e31 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -81,8 +81,14 @@ module Types
description: 'Default merge commit message of the merge request'
field :merge_ongoing, GraphQL::BOOLEAN_TYPE, method: :merge_ongoing?, null: false,
description: 'Indicates if a merge is currently occurring'
- field :source_branch_exists, GraphQL::BOOLEAN_TYPE, method: :source_branch_exists?, null: false,
+ field :source_branch_exists, GraphQL::BOOLEAN_TYPE,
+ null: false, calls_gitaly: true,
+ method: :source_branch_exists?,
description: 'Indicates if the source branch of the merge request exists'
+ field :target_branch_exists, GraphQL::BOOLEAN_TYPE,
+ null: false, calls_gitaly: true,
+ method: :target_branch_exists?,
+ description: 'Indicates if the target branch of the merge request exists'
field :mergeable_discussions_state, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged'
field :web_url, GraphQL::STRING_TYPE, null: true,
diff --git a/app/graphql/types/permission_types/merge_request.rb b/app/graphql/types/permission_types/merge_request.rb
index d877fc177d2..28b7ebd2af6 100644
--- a/app/graphql/types/permission_types/merge_request.rb
+++ b/app/graphql/types/permission_types/merge_request.rb
@@ -3,6 +3,11 @@
module Types
module PermissionTypes
class MergeRequest < BasePermissionType
+ PERMISSION_FIELDS = %i[push_to_source_branch
+ remove_source_branch
+ cherry_pick_on_current_merge_request
+ revert_on_current_merge_request].freeze
+
present_using MergeRequestPresenter
description 'Check permissions for the current user on a merge request'
graphql_name 'MergeRequestPermissions'
@@ -10,10 +15,9 @@ module Types
abilities :read_merge_request, :admin_merge_request,
:update_merge_request, :create_note
- permission_field :push_to_source_branch, method: :can_push_to_source_branch?, calls_gitaly: true
- permission_field :remove_source_branch, method: :can_remove_source_branch?, calls_gitaly: true
- permission_field :cherry_pick_on_current_merge_request, method: :can_cherry_pick_on_current_merge_request?
- permission_field :revert_on_current_merge_request, method: :can_revert_on_current_merge_request?
+ PERMISSION_FIELDS.each do |field_name|
+ permission_field field_name, method: :"can_#{field_name}?", calls_gitaly: true
+ end
end
end
end
diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb
index 81ca9d6d123..2a4cbe2dc4b 100644
--- a/app/services/releases/create_service.rb
+++ b/app/services/releases/create_service.rb
@@ -49,6 +49,8 @@ module Releases
notify_create_release(release)
+ create_evidence!(release)
+
success(tag: tag, release: release)
rescue => e
error(e.message, 400)
@@ -70,5 +72,15 @@ module Releases
milestones: milestones
)
end
+
+ def create_evidence!(release)
+ return if release.historical_release?
+
+ if release.upcoming_release?
+ CreateEvidenceWorker.perform_at(release.released_at, release.id)
+ else
+ CreateEvidenceWorker.perform_async(release.id)
+ end
+ end
end
end
diff --git a/app/views/shared/_promo.html.haml b/app/views/shared/_promo.html.haml
index 0f31b60d8d3..855f6b9c1f4 100644
--- a/app/views/shared/_promo.html.haml
+++ b/app/views/shared/_promo.html.haml
@@ -1,5 +1,5 @@
.gitlab-promo
- = link_to 'Homepage', promo_url
- = link_to 'Blog', promo_url + '/blog/'
+ = link_to _('Homepage'), promo_url
+ = link_to _('Blog'), promo_url + '/blog/'
= link_to '@gitlab', 'https://twitter.com/gitlab'
- = link_to 'Requests', 'https://gitlab.com/gitlab-org/gitlab-foss/blob/master/CONTRIBUTING.md#feature-proposals'
+ = link_to _('Requests'), 'https://gitlab.com/gitlab-org/gitlab-foss/blob/master/CONTRIBUTING.md#feature-proposals'