diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-05 15:10:36 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-01-05 15:10:36 +0300 |
commit | 797182cd82922765fe79a13bc0ed6bd5672d4283 (patch) | |
tree | 82d0ea1a8378560de4aeb5c1e446b74282035d60 /app | |
parent | a060caf3db3090d75284a71a08ab1cf697afad97 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
27 files changed, 185 insertions, 102 deletions
diff --git a/app/assets/javascripts/diffs/utils/uuids.js b/app/assets/javascripts/diffs/utils/uuids.js index 12448350e62..1fe5f9f6499 100644 --- a/app/assets/javascripts/diffs/utils/uuids.js +++ b/app/assets/javascripts/diffs/utils/uuids.js @@ -11,7 +11,7 @@ * @typedef {String} UUIDv4 */ -import MersenneTwister from 'mersenne-twister'; +import { MersenneTwister } from 'fast-mersenne-twister'; import stringHash from 'string-hash'; import { isString } from 'lodash'; import { v4 } from 'uuid'; @@ -49,7 +49,7 @@ function randomValuesForUuid(prng) { const buffer = new ArrayBuffer(4); const view = new DataView(buffer); - view.setUint32(0, prng.random_int()); + view.setUint32(0, prng.randomNumber()); randomValues.push(view.getUint8(0), view.getUint8(1), view.getUint8(2), view.getUint8(3)); } diff --git a/app/assets/javascripts/jira_connect/api.js b/app/assets/javascripts/jira_connect/api.js new file mode 100644 index 00000000000..55f2ef4f820 --- /dev/null +++ b/app/assets/javascripts/jira_connect/api.js @@ -0,0 +1,24 @@ +import axios from 'axios'; + +const getJwt = async () => { + return AP.context.getToken(); +}; + +export const addSubscription = async (addPath, namespace) => { + const jwt = await getJwt(); + + return axios.post(addPath, { + jwt, + namespace_path: namespace, + }); +}; + +export const removeSubscription = async (removePath) => { + const jwt = await getJwt(); + + return axios.delete(removePath, { + params: { + jwt, + }, + }); +}; diff --git a/app/assets/javascripts/jira_connect/components/app.vue b/app/assets/javascripts/jira_connect/components/app.vue index 490bf2fdd66..4a58113db1f 100644 --- a/app/assets/javascripts/jira_connect/components/app.vue +++ b/app/assets/javascripts/jira_connect/components/app.vue @@ -1,6 +1,9 @@ <script> +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; + export default { name: 'JiraConnectApp', + mixins: [glFeatureFlagsMixin()], computed: { state() { return this.$root.$data.state || {}; @@ -8,9 +11,17 @@ export default { error() { return this.state.error; }, + showNewUi() { + return this.glFeatures.newJiraConnectUi; + }, }, }; </script> + <template> - <div></div> + <div> + <div v-if="showNewUi"> + <h3>{{ s__('Integrations|Linked namespaces') }}</h3> + </div> + </div> </template> diff --git a/app/assets/javascripts/jira_connect/index.js b/app/assets/javascripts/jira_connect/index.js index cc18d67aebd..bd261750ccd 100644 --- a/app/assets/javascripts/jira_connect/index.js +++ b/app/assets/javascripts/jira_connect/index.js @@ -1,6 +1,11 @@ import Vue from 'vue'; import $ from 'jquery'; +import setConfigs from '@gitlab/ui/dist/config'; +import Translate from '~/vue_shared/translate'; +import GlFeatureFlagsPlugin from '~/vue_shared/gl_feature_flags_plugin'; + import App from './components/app.vue'; +import { addSubscription, removeSubscription } from '~/jira_connect/api'; const store = { state: { @@ -27,46 +32,35 @@ const initJiraFormHandlers = () => { alert(error); }; - AP.getLocation((location) => { - $('.js-jira-connect-sign-in').each(function updateSignInLink() { - const updatedLink = `${$(this).attr('href')}?return_to=${location}`; - $(this).attr('href', updatedLink); + if (typeof AP.getLocation === 'function') { + AP.getLocation((location) => { + $('.js-jira-connect-sign-in').each(function updateSignInLink() { + const updatedLink = `${$(this).attr('href')}?return_to=${location}`; + $(this).attr('href', updatedLink); + }); }); - }); + } $('#add-subscription-form').on('submit', function onAddSubscriptionForm(e) { - const actionUrl = $(this).attr('action'); + const addPath = $(this).attr('action'); + const namespace = $('#namespace-input').val(); + e.preventDefault(); - AP.context.getToken((token) => { - // eslint-disable-next-line no-jquery/no-ajax - $.post(actionUrl, { - jwt: token, - namespace_path: $('#namespace-input').val(), - format: 'json', - }) - .done(reqComplete) - .fail((err) => reqFailed(err, 'Failed to add namespace. Please try again.')); - }); + addSubscription(addPath, namespace) + .then(reqComplete) + .catch((err) => reqFailed(err.response.data, 'Failed to add namespace. Please try again.')); }); $('.remove-subscription').on('click', function onRemoveSubscriptionClick(e) { - const href = $(this).attr('href'); + const removePath = $(this).attr('href'); e.preventDefault(); - AP.context.getToken((token) => { - // eslint-disable-next-line no-jquery/no-ajax - $.ajax({ - url: href, - method: 'DELETE', - data: { - jwt: token, - format: 'json', - }, - }) - .done(reqComplete) - .fail((err) => reqFailed(err, 'Failed to remove namespace. Please try again.')); - }); + removeSubscription(removePath) + .then(reqComplete) + .catch((err) => + reqFailed(err.response.data, 'Failed to remove namespace. Please try again.'), + ); }); }; @@ -75,6 +69,14 @@ function initJiraConnect() { initJiraFormHandlers(); + if (!el) { + return null; + } + + setConfigs(); + Vue.use(Translate); + Vue.use(GlFeatureFlagsPlugin); + return new Vue({ el, data: { diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss index c3e49da92a6..ff989b474ad 100644 --- a/app/assets/stylesheets/page_bundles/jira_connect.scss +++ b/app/assets/stylesheets/page_bundles/jira_connect.scss @@ -2,6 +2,11 @@ // We should only import styles that we actually use. // @import '@gitlab/ui/src/scss/gitlab_ui'; +@import '@gitlab/ui/src/scss/bootstrap'; +@import 'bootstrap-vue/src/index'; + +@import '@gitlab/ui/src/scss/utilities'; + $atlaskit-border-color: #dfe1e6; .ac-content { @@ -40,14 +45,16 @@ $header-height: 40px; } .jira-connect-user { - float: right; - position: relative; - top: -30px; + font-size: $gl-font-size; + position: fixed; + top: 10px; + right: 20px; } .jira-connect-app { margin-top: $header-height; max-width: 600px; + min-height: 95vh; padding-top: 48px; padding-left: 16px; padding-right: 16px; @@ -108,5 +115,6 @@ svg { } .browser-limitations-notice { + font-size: $gl-font-size; margin-top: 32px; } diff --git a/app/assets/stylesheets/page_bundles/wiki.scss b/app/assets/stylesheets/page_bundles/wiki.scss index eb34e7f3876..9f0fa137910 100644 --- a/app/assets/stylesheets/page_bundles/wiki.scss +++ b/app/assets/stylesheets/page_bundles/wiki.scss @@ -15,11 +15,6 @@ padding: 11px 0; } - .wiki-page-title { - margin: 0; - font-size: 22px; - } - .wiki-last-edit-by { display: block; color: var(--gray-500, $gray-500); diff --git a/app/controllers/jira_connect/subscriptions_controller.rb b/app/controllers/jira_connect/subscriptions_controller.rb index 3ff12f29f10..161280a05fc 100644 --- a/app/controllers/jira_connect/subscriptions_controller.rb +++ b/app/controllers/jira_connect/subscriptions_controller.rb @@ -19,6 +19,9 @@ class JiraConnect::SubscriptionsController < JiraConnect::ApplicationController before_action :allow_rendering_in_iframe, only: :index before_action :verify_qsh_claim!, only: :index before_action :authenticate_user!, only: :create + before_action do + push_frontend_feature_flag(:new_jira_connect_ui, type: :development, default_enabled: :yaml) + end def index @subscriptions = current_jira_installation.subscriptions.preload_namespace_route diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb new file mode 100644 index 00000000000..c30eb1b007a --- /dev/null +++ b/app/helpers/jira_connect_helper.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module JiraConnectHelper + def new_jira_connect_ui? + Feature.enabled?(:new_jira_connect_ui, type: :development, default_enabled: :yaml) + end +end diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index f04fcf34f43..2868e3ac80a 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -196,6 +196,10 @@ module Issuable is_a?(Issue) end + def supports_assignee? + false + end + def severity return IssuableSeverity::DEFAULT unless supports_severity? diff --git a/app/models/concerns/issue_available_features.rb b/app/models/concerns/issue_available_features.rb index 886db133a94..a9768d93148 100644 --- a/app/models/concerns/issue_available_features.rb +++ b/app/models/concerns/issue_available_features.rb @@ -9,7 +9,9 @@ module IssueAvailableFeatures class_methods do # EE only features are listed on EE::IssueAvailableFeatures def available_features_for_issue_types - {}.with_indifferent_access + { + assignee: %w(issue incident) + }.with_indifferent_access end end diff --git a/app/models/environment.rb b/app/models/environment.rb index 31a95bb1b5d..4f7f688a040 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -405,6 +405,11 @@ class Environment < ApplicationRecord deployment_platform.patch_ingress(deployment_namespace, ingress, data) end + def clear_all_caches + expire_etag_cache + clear_reactive_cache! + end + private def rollout_status_available? diff --git a/app/models/issue.rb b/app/models/issue.rb index 253f4465cd9..5da9f67f6ef 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -434,6 +434,10 @@ class Issue < ApplicationRecord moved_to || duplicated_to end + def supports_assignee? + issue_type_supports?(:assignee) + end + private def ensure_metrics diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 5b0b8dc4e55..db066184e91 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1774,6 +1774,10 @@ class MergeRequest < ApplicationRecord false end + def supports_assignee? + true + end + private def with_rebase_lock diff --git a/app/serializers/merge_request_poll_cached_widget_entity.rb b/app/serializers/merge_request_poll_cached_widget_entity.rb index 080b6554de1..1db4ec37d4a 100644 --- a/app/serializers/merge_request_poll_cached_widget_entity.rb +++ b/app/serializers/merge_request_poll_cached_widget_entity.rb @@ -104,6 +104,16 @@ class MergeRequestPollCachedWidgetEntity < IssuableEntity presenter(merge_request).api_unapprove_path end + expose :blob_path do + expose :head_path, if: -> (mr, _) { mr.source_branch_sha } do |merge_request| + project_blob_path(merge_request.project, merge_request.source_branch_sha) + end + + expose :base_path, if: -> (mr, _) { mr.diff_base_sha } do |merge_request| + project_blob_path(merge_request.project, merge_request.diff_base_sha) + end + end + private delegate :current_user, to: :request diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb index afd4d5b9a2b..ca4e16bc5ff 100644 --- a/app/serializers/merge_request_widget_entity.rb +++ b/app/serializers/merge_request_widget_entity.rb @@ -115,16 +115,6 @@ class MergeRequestWidgetEntity < Grape::Entity end end - expose :blob_path do - expose :head_path, if: -> (mr, _) { mr.source_branch_sha } do |merge_request| - project_blob_path(merge_request.project, merge_request.source_branch_sha) - end - - expose :base_path, if: -> (mr, _) { mr.diff_base_sha } do |merge_request| - project_blob_path(merge_request.project, merge_request.diff_base_sha) - end - end - expose :codeclimate, if: -> (mr, _) { head_pipeline_downloadable_path_for_report_type(:codequality) } do expose :head_path do |merge_request| head_pipeline_downloadable_path_for_report_type(:codequality) diff --git a/app/services/environments/canary_ingress/update_service.rb b/app/services/environments/canary_ingress/update_service.rb index 474c3de23d9..2b510280873 100644 --- a/app/services/environments/canary_ingress/update_service.rb +++ b/app/services/environments/canary_ingress/update_service.rb @@ -24,6 +24,7 @@ module Environments end if environment.patch_ingress(canary_ingress, patch_data) + environment.clear_all_caches success else error(_('Failed to update the Canary Ingress.'), :bad_request) diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb index 1bff70e6c2e..c7107e2fa56 100644 --- a/app/services/groups/destroy_service.rb +++ b/app/services/groups/destroy_service.rb @@ -29,17 +29,32 @@ module Groups group.chat_team&.remove_mattermost_team(current_user) - user_ids_for_project_authorizations_refresh = group.user_ids_for_project_authorizations + # If any other groups are shared with the group that is being destroyed, + # we should specifically trigger update of all project authorizations + # for users that are the members of this group. + # If not, the project authorization records of these users to projects within the shared groups + # will never be removed, causing inconsistencies with access permissions. + if any_other_groups_are_shared_with_this_group? + user_ids_for_project_authorizations_refresh = group.user_ids_for_project_authorizations + end group.destroy - UserProjectAccessChangedService - .new(user_ids_for_project_authorizations_refresh) - .execute(blocking: true) + if user_ids_for_project_authorizations_refresh.present? + UserProjectAccessChangedService + .new(user_ids_for_project_authorizations_refresh) + .execute(blocking: true) + end group end # rubocop: enable CodeReuse/ActiveRecord + + private + + def any_other_groups_are_shared_with_this_group? + group.shared_group_links.any? + end end end diff --git a/app/views/admin/dev_ops_report/show.html.haml b/app/views/admin/dev_ops_report/show.html.haml index 75398f3aa21..19ce285162f 100644 --- a/app/views/admin/dev_ops_report/show.html.haml +++ b/app/views/admin/dev_ops_report/show.html.haml @@ -3,7 +3,7 @@ .container .gl-mt-3 - - if Gitlab.ee? && Feature.enabled?(:devops_adoption_feature, default_enabled: true) && License.feature_available?(:devops_adoption) + - if Gitlab.ee? && License.feature_available?(:devops_adoption) = render_if_exists 'admin/dev_ops_report/devops_tabs' - else = render 'report' diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml index b826a1b6fc6..90a92f5c6d5 100644 --- a/app/views/jira_connect/subscriptions/index.html.haml +++ b/app/views/jira_connect/subscriptions/index.html.haml @@ -23,15 +23,16 @@ - else .js-jira-connect-app - %form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path } - .ak-field-group - %label - GitLab namespace + - unless new_jira_connect_ui? + %form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path } + .ak-field-group + %label + GitLab namespace - .ak-field-group.field-group-input - %input#namespace-input.ak-field-text{ type: 'text', required: true, placeholder: 'e.g. "MyCompany" or "MyCompany/GroupName"' } - %button.ak-button.ak-button__appearance-primary{ type: 'submit' } - Link namespace to Jira + .ak-field-group.field-group-input + %input#namespace-input.ak-field-text{ type: 'text', required: true, placeholder: 'e.g. "MyCompany" or "MyCompany/GroupName"' } + %button.ak-button.ak-button__appearance-primary{ type: 'submit' } + Link namespace to Jira - if @subscriptions.present? %table.subscriptions @@ -49,6 +50,7 @@ - else %h4.empty-subscriptions No linked namespaces + %p= s_('Integrations|Namespaces are your GitLab groups and subgroups that will be linked to this Jira instance.') %p.browser-limitations-notice %strong Browser limitations: diff --git a/app/views/layouts/jira_connect.html.haml b/app/views/layouts/jira_connect.html.haml index 0d4ecfc5a10..d996b3387a3 100644 --- a/app/views/layouts/jira_connect.html.haml +++ b/app/views/layouts/jira_connect.html.haml @@ -3,8 +3,9 @@ %meta{ content: "text/html; charset=utf-8", "http-equiv" => "Content-Type" } %title GitLab - = stylesheet_link_tag 'https://unpkg.com/@atlaskit/css-reset@3.0.6/dist/bundle.css' - = stylesheet_link_tag 'https://unpkg.com/@atlaskit/reduced-ui-pack@10.5.5/dist/bundle.css' + - unless new_jira_connect_ui? + = stylesheet_link_tag 'https://unpkg.com/@atlaskit/css-reset@3.0.6/dist/bundle.css' + = stylesheet_link_tag 'https://unpkg.com/@atlaskit/reduced-ui-pack@10.5.5/dist/bundle.css' = yield :page_specific_styles = javascript_include_tag 'https://connect-cdn.atl-paas.net/all.js' diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml index c4bf2d20ecf..4d00762760e 100644 --- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml +++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml @@ -16,7 +16,7 @@ %code v* or %code *-release - are supported + are supported. .form-group.row %label.col-md-2.text-right{ for: 'create_access_levels_attributes' } Allowed to create: diff --git a/app/views/projects/protected_tags/shared/_index.html.haml b/app/views/projects/protected_tags/shared/_index.html.haml index 4bf3ce09fc7..5734b7dc3c9 100644 --- a/app/views/projects/protected_tags/shared/_index.html.haml +++ b/app/views/projects/protected_tags/shared/_index.html.haml @@ -7,16 +7,14 @@ %button.btn.js-settings-toggle{ type: 'button' } = expanded ? 'Collapse' : 'Expand' %p - Limit access to creating and updating tags. + Limit access to creating and updating tags. #{link_to "What are protected tags?", help_page_path("user/project/protected_tags")} .settings-content %p - By default, protected tags are designed to: + By default, protected tags protect your code and: %ul - %li Prevent tag creation by everybody except Maintainers - %li Prevent <strong>anyone</strong> from updating the tag - %li Prevent <strong>anyone</strong> from deleting the tag - - %p Read more about #{link_to "protected tags", help_page_path("user/project/protected_tags")}. + %li Allow only users with Maintainer #{link_to "permissions", help_page_path("user/permissions")} to create tags. + %li Prevent <strong>anyone</strong> from updating tags. + %li Prevent <strong>anyone</strong> from deleting tags. - if can? current_user, :admin_project, @project = yield :create_protected_tag diff --git a/app/views/projects/protected_tags/shared/_tags_list.html.haml b/app/views/projects/protected_tags/shared/_tags_list.html.haml index 382ea848243..a5a43072744 100644 --- a/app/views/projects/protected_tags/shared/_tags_list.html.haml +++ b/app/views/projects/protected_tags/shared/_tags_list.html.haml @@ -1,9 +1,9 @@ .protected-tags-list.js-protected-tags-list - if @protected_tags.empty? .card-header - Protected tag (#{@protected_tags_count}) + Protected tags (#{@protected_tags_count}) %p.settings-message.text-center - There are currently no protected tags, protect a tag with the form above. + No tags are protected. - else - can_admin_project = can?(current_user, :admin_project, @project) @@ -16,7 +16,7 @@ %col %thead %tr - %th Protected tag (#{@protected_tags_count}) + %th Protected tags (#{@protected_tags_count}) %th Last commit %th Allowed to create - if can_admin_project diff --git a/app/views/shared/wikis/diff.html.haml b/app/views/shared/wikis/diff.html.haml index 68bbbd66f4a..19167f04855 100644 --- a/app/views/shared/wikis/diff.html.haml +++ b/app/views/shared/wikis/diff.html.haml @@ -5,12 +5,11 @@ .wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row = wiki_sidebar_toggle_button - .nav-text - %h2.wiki-page-title - = link_to_wiki_page @page - %span.light - · - = _('Changes') + %h3.page-title.gl-flex-fill-1 + = link_to_wiki_page @page + %span.light + · + = _('Changes') .nav-controls.pb-md-3.pb-lg-0 = link_to wiki_page_path(@wiki, @page, action: :history), class: 'btn gl-button', role: 'button', data: { qa_selector: 'page_history_button' } do diff --git a/app/views/shared/wikis/edit.html.haml b/app/views/shared/wikis/edit.html.haml index b289c018015..c2b0e474c03 100644 --- a/app/views/shared/wikis/edit.html.haml +++ b/app/views/shared/wikis/edit.html.haml @@ -6,15 +6,14 @@ .wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row = wiki_sidebar_toggle_button - .nav-text - %h2.wiki-page-title - - if @page.persisted? - = link_to_wiki_page @page - %span.light - · - = s_("Wiki|Edit Page") - - else - = s_("Wiki|Create New Page") + %h3.page-title.gl-flex-fill-1 + - if @page.persisted? + = link_to_wiki_page @page + %span.light + · + = s_("Wiki|Edit Page") + - else + = s_("Wiki|Create New Page") .nav-controls.pb-md-3.pb-lg-0 - if @page.persisted? diff --git a/app/views/shared/wikis/history.html.haml b/app/views/shared/wikis/history.html.haml index 50ccfdeabd5..b1dcd2cd400 100644 --- a/app/views/shared/wikis/history.html.haml +++ b/app/views/shared/wikis/history.html.haml @@ -4,12 +4,11 @@ .wiki-page-header.top-area.has-sidebar-toggle.flex-column.flex-lg-row = wiki_sidebar_toggle_button - .nav-text - %h2.wiki-page-title - = link_to_wiki_page @page - %span.light - · - = _('History') + %h3.page-title + = link_to_wiki_page @page + %span.light + · + = _('History') .prepend-top-default.gl-mb-3 .table-holder diff --git a/app/views/shared/wikis/pages.html.haml b/app/views/shared/wikis/pages.html.haml index 76fc9510740..f5ba1c83de4 100644 --- a/app/views/shared/wikis/pages.html.haml +++ b/app/views/shared/wikis/pages.html.haml @@ -6,9 +6,9 @@ .wiki-page-header.top-area.flex-column.flex-lg-row - .nav-text.flex-fill - %h2.wiki-page-title - = s_("Wiki|Wiki Pages") + + %h3.page-title.gl-flex-fill-1 + = s_("Wiki|Wiki Pages") .nav-controls.pb-md-3.pb-lg-0 = link_to wiki_path(@wiki, action: :git_access), class: 'btn gl-button' do |