diff options
Diffstat (limited to 'app')
20 files changed, 197 insertions, 23 deletions
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js index 9f547471170..b07f951346e 100644 --- a/app/assets/javascripts/blob_edit/blob_bundle.js +++ b/app/assets/javascripts/blob_edit/blob_bundle.js @@ -17,6 +17,11 @@ export default () => { const currentAction = $('.js-file-title').data('currentAction'); const projectId = editBlobForm.data('project-id'); const commitButton = $('.js-commit-button'); + const cancelLink = $('.btn.btn-cancel'); + + cancelLink.on('click', () => { + window.onbeforeunload = null; + }); commitButton.on('click', () => { window.onbeforeunload = null; diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 4156fe0d229..07c938a0021 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -413,7 +413,7 @@ Please check your network connection and try again.`; </template> </ul> <div - v-if="!isRepliesCollapsed" + v-if="!isRepliesCollapsed || !hasReplies" :class="{ 'is-replying': isReplying }" class="discussion-reply-holder" > diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js index 02a56685a35..f99023ad8e7 100644 --- a/app/assets/javascripts/pages/projects/issues/form.js +++ b/app/assets/javascripts/pages/projects/issues/form.js @@ -17,7 +17,7 @@ export default () => { new MilestoneSelect(); new IssuableTemplateSelectors(); - if (gon.features.issueSuggestions && gon.features.graphql) { + if (gon.features.graphql) { initSuggestions(); } }; diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue new file mode 100644 index 00000000000..bd65a225d8f --- /dev/null +++ b/app/assets/javascripts/releases/components/release_block.vue @@ -0,0 +1,145 @@ +<script> +import { GlTooltipDirective, GlLink } from '@gitlab/ui'; +import Icon from '~/vue_shared/components/icon.vue'; +import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; +import timeagoMixin from '~/vue_shared/mixins/timeago'; +import { sprintf } from '../../locale'; + +export default { + name: 'ReleaseBlock', + components: { + GlLink, + Icon, + UserAvatarLink, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + mixins: [timeagoMixin], + props: { + name: { + type: String, + required: true, + }, + tag: { + type: String, + required: true, + }, + commit: { + type: Object, + required: true, + }, + description: { + type: String, + required: false, + default: '', + }, + author: { + type: Object, + required: true, + }, + createdAt: { + type: String, + required: false, + default: '', + }, + assetsCount: { + type: Number, + required: false, + default: 0, + }, + sources: { + type: Array, + required: false, + default: () => [], + }, + links: { + type: Array, + required: false, + default: () => [], + }, + }, + computed: { + releasedTimeAgo() { + return sprintf('released %{time}', { + time: this.timeFormated(this.createdAt), + }); + }, + userImageAltDescription() { + return this.author && this.author.username + ? sprintf("%{username}'s avatar", { username: this.author.username }) + : null; + }, + }, +}; +</script> +<template> + <div class="card"> + <div class="card-body"> + <h2 class="card-title mt-0">{{ name }}</h2> + + <div class="card-subtitle d-flex flex-wrap text-secondary"> + <div class="append-right-8"> + <icon name="commit" class="align-middle" /> + <span v-gl-tooltip.bottom :title="commit.title">{{ commit.short_id }}</span> + </div> + + <div class="append-right-8"> + <icon name="tag" class="align-middle" /> + <span v-gl-tooltip.bottom :title="__('Tag')">{{ tag }}</span> + </div> + + <div class="append-right-4"> + • + <span v-gl-tooltip.bottom :title="tooltipTitle(createdAt)">{{ releasedTimeAgo }}</span> + </div> + + <div class="d-flex"> + by + <user-avatar-link + class="prepend-left-4" + :link-href="author.path" + :img-src="author.avatar_url" + :img-alt="userImageAltDescription" + :tooltip-text="author.username" + /> + </div> + </div> + + <div class="card-text prepend-top-default"> + <b> + {{ __('Assets') }} <span class="js-assets-count badge badge-pill">{{ assetsCount }}</span> + </b> + + <ul class="pl-0 mb-0 prepend-top-8 list-unstyled js-assets-list"> + <li v-for="link in links" :key="link.name" class="append-bottom-8"> + <gl-link v-gl-tooltip.bottom :title="__('Download asset')" :href="link.url"> + <icon name="package" class="align-middle append-right-4" /> {{ link.name }} + </gl-link> + </li> + </ul> + + <div class="dropdown"> + <button + type="button" + class="btn btn-link" + data-toggle="dropdown" + aria-haspopup="true" + aria-expanded="false" + > + <icon name="doc-code" class="align-top append-right-4" /> {{ __('Source code') }} + <icon name="arrow-down" /> + </button> + + <div class="js-sources-dropdown dropdown-menu"> + <li v-for="asset in sources" :key="asset.url"> + <gl-link :href="asset.url">{{ __('Download') }} {{ asset.format }}</gl-link> + </li> + </div> + </div> + </div> + + <div class="card-text prepend-top-default"><div v-html="description"></div></div> + </div> + </div> +</template> diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index b47b1cb76dc..afcb230797a 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -534,8 +534,9 @@ .dropdown-title { position: relative; - padding: 2px 25px 10px; - margin: 0 10px 10px; + padding: $dropdown-item-padding-y $dropdown-item-padding-x; + padding-bottom: #{2 * $dropdown-item-padding-y}; + margin-bottom: $dropdown-item-padding-y; font-weight: $gl-font-weight-bold; line-height: 1; text-align: center; diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb index 6ea4758ec32..3ef03bc9622 100644 --- a/app/controllers/graphql_controller.rb +++ b/app/controllers/graphql_controller.rb @@ -43,6 +43,6 @@ class GraphqlController < ApplicationController end def check_graphql_feature_flag! - render_404 unless Feature.enabled?(:graphql) + render_404 unless Gitlab::Graphql.enabled? end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index c6ab6b4642e..5ed46fc0545 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -268,7 +268,6 @@ class Projects::IssuesController < Projects::ApplicationController end def set_suggested_issues_feature_flags - push_frontend_feature_flag(:graphql) - push_frontend_feature_flag(:issue_suggestions) + push_frontend_feature_flag(:graphql, default_enabled: true) end end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index d06022a0fb7..2cdb4780412 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -68,11 +68,7 @@ module Ci # this `Hash` with new values. enum_with_nil source: ::Ci::PipelineEnums.sources - enum_with_nil config_source: { - unknown_source: nil, - repository_source: 1, - auto_devops_source: 2 - } + enum_with_nil config_source: ::Ci::PipelineEnums.config_sources # We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily # extend this `Hash` with new values. diff --git a/app/models/ci/pipeline_enums.rb b/app/models/ci/pipeline_enums.rb index c0f16066e0b..2994aaae4aa 100644 --- a/app/models/ci/pipeline_enums.rb +++ b/app/models/ci/pipeline_enums.rb @@ -25,5 +25,15 @@ module Ci merge_request: 10 } end + + # Returns the `Hash` to use for creating the `config_sources` enum for + # `Ci::Pipeline`. + def self.config_sources + { + unknown_source: nil, + repository_source: 1, + auto_devops_source: 2 + } + end end end diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb index 168a24da738..0c72d7d8340 100644 --- a/app/models/clusters/applications/knative.rb +++ b/app/models/clusters/applications/knative.rb @@ -3,7 +3,7 @@ module Clusters module Applications class Knative < ActiveRecord::Base - VERSION = '0.1.3'.freeze + VERSION = '0.2.2'.freeze REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze FETCH_IP_ADDRESS_DELAY = 30.seconds diff --git a/app/models/release.rb b/app/models/release.rb index cba80ad30ca..7a09ee459a6 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -6,6 +6,7 @@ class Release < ActiveRecord::Base cache_markdown_field :description belongs_to :project + belongs_to :author, class_name: 'User' validates :description, :project, :tag, presence: true end diff --git a/app/models/user.rb b/app/models/user.rb index dbd754dd25a..f20756d1cc3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -130,6 +130,7 @@ class User < ActiveRecord::Base has_many :issues, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :merge_requests, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :events, dependent: :destroy, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent + has_many :releases, dependent: :nullify, foreign_key: :author_id # rubocop:disable Cop/ActiveRecordDependent has_many :subscriptions, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :oauth_applications, class_name: 'Doorkeeper::Application', as: :owner, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_one :abuse_report, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb index 7e6eccb648c..0473bb8c72a 100644 --- a/app/presenters/clusters/cluster_presenter.rb +++ b/app/presenters/clusters/cluster_presenter.rb @@ -12,6 +12,14 @@ module Clusters can?(current_user, :update_cluster, cluster) && created? end + def cluster_type_description + if cluster.project_type? + s_("ClusterIntegration|Project cluster") + elsif cluster.group_type? + s_("ClusterIntegration|Group cluster") + end + end + def show_path if cluster.project_type? project_cluster_path(project, cluster) diff --git a/app/serializers/issue_board_entity.rb b/app/serializers/issue_board_entity.rb index 58ab804a3c8..e3dc43240c6 100644 --- a/app/serializers/issue_board_entity.rb +++ b/app/serializers/issue_board_entity.rb @@ -17,7 +17,7 @@ class IssueBoardEntity < Grape::Entity end expose :milestone, expose_nil: false do |issue| - API::Entities::Project.represent issue.milestone, only: [:id, :title] + API::Entities::Milestone.represent issue.milestone, only: [:id, :title] end expose :assignees do |issue| diff --git a/app/services/create_release_service.rb b/app/services/create_release_service.rb index 8d1fdbe11c3..ab2dc5337aa 100644 --- a/app/services/create_release_service.rb +++ b/app/services/create_release_service.rb @@ -13,8 +13,13 @@ class CreateReleaseService < BaseService if release error('Release already exists', 409) else - release = project.releases.new({ tag: tag_name, description: release_description }) - release.save + release = project.releases.create!( + tag: tag_name, + name: tag_name, + sha: existing_tag.dereferenced_target.sha, + author: current_user, + description: release_description + ) success(release) end diff --git a/app/services/labels/promote_service.rb b/app/services/labels/promote_service.rb index f30ad706c63..3c0e6196d4f 100644 --- a/app/services/labels/promote_service.rb +++ b/app/services/labels/promote_service.rb @@ -57,7 +57,7 @@ module Labels def update_issuables(new_label, label_ids) LabelLink .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord @@ -65,7 +65,7 @@ module Labels def update_resource_label_events(new_label, label_ids) ResourceLabelEvent .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord @@ -73,7 +73,7 @@ module Labels def update_issue_board_lists(new_label, label_ids) List .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord @@ -81,7 +81,7 @@ module Labels def update_priorities(new_label, label_ids) LabelPriority .where(label: label_ids) - .update_all(label_id: new_label) + .update_all(label_id: new_label.id) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb index 1c4a8d05be6..f9b9781ad5f 100644 --- a/app/services/projects/lfs_pointers/lfs_download_service.rb +++ b/app/services/projects/lfs_pointers/lfs_download_service.rb @@ -4,6 +4,8 @@ module Projects module LfsPointers class LfsDownloadService < BaseService + VALID_PROTOCOLS = %w[http https].freeze + # rubocop: disable CodeReuse/ActiveRecord def execute(oid, url) return unless project&.lfs_enabled? && oid.present? && url.present? @@ -11,6 +13,7 @@ module Projects return if LfsObject.exists?(oid: oid) sanitized_uri = Gitlab::UrlSanitizer.new(url) + Gitlab::UrlBlocker.validate!(sanitized_uri.sanitized_url, protocols: VALID_PROTOCOLS) with_tmp_file(oid) do |file| size = download_and_save_file(file, sanitized_uri) diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb index 35390f5082c..6bb9bb3988e 100644 --- a/app/services/tags/create_service.rb +++ b/app/services/tags/create_service.rb @@ -20,7 +20,7 @@ module Tags end if new_tag - if release_description + if release_description.present? CreateReleaseService.new(@project, @current_user) .execute(tag_name, release_description) end diff --git a/app/views/clusters/clusters/_cluster.html.haml b/app/views/clusters/clusters/_cluster.html.haml index adeca013749..e15de3d504d 100644 --- a/app/views/clusters/clusters/_cluster.html.haml +++ b/app/views/clusters/clusters/_cluster.html.haml @@ -13,4 +13,4 @@ .table-mobile-header{ role: "rowheader" } .table-mobile-content %span.badge.badge-light - = cluster.project_type? ? s_("ClusterIntegration|Project cluster") : s_("ClusterIntegration|Group cluster") + = cluster.cluster_type_description diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index 1618655182c..c6a391ae563 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -17,7 +17,7 @@ = render 'shared/issuable/form/template_selector', issuable: issuable = render 'shared/issuable/form/title', issuable: issuable, form: form, has_wip_commits: commits && commits.detect(&:work_in_progress?) -- if Feature.enabled?(:issue_suggestions) && Feature.enabled?(:graphql) +- if Gitlab::Graphql.enabled? #js-suggestions{ data: { project_path: @project.full_path } } = render 'shared/form_elements/description', model: issuable, form: form, project: project |