diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-14 09:08:43 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-14 09:08:43 +0000 |
commit | 733befe96ad19f5a02e442c4a9cc8059d3aabbda (patch) | |
tree | dcabd344df040e536a242edc4e3121fb3efca142 /app | |
parent | 10213bf3b26c3c21f7683471d35d1cd052c41e9c (diff) | |
download | gitlab-ce-733befe96ad19f5a02e442c4a9cc8059d3aabbda.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
21 files changed, 208 insertions, 80 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 76f3020c5c2..4dc4ce543e9 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -24,6 +24,7 @@ const Api = { projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes', projectMergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions', projectRunnersPath: '/api/:version/projects/:id/runners', + projectProtectedBranchesPath: '/api/:version/projects/:id/protected_branches', mergeRequestsPath: '/api/:version/merge_requests', groupLabelsPath: '/groups/:namespace_path/-/labels', issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key', @@ -220,6 +221,22 @@ const Api = { return axios.get(url, config); }, + projectProtectedBranches(id, query = '') { + const url = Api.buildUrl(Api.projectProtectedBranchesPath).replace( + ':id', + encodeURIComponent(id), + ); + + return axios + .get(url, { + params: { + search: query, + per_page: DEFAULT_PER_PAGE, + }, + }) + .then(({ data }) => data); + }, + mergeRequests(params = {}) { const url = Api.buildUrl(Api.mergeRequestsPath); diff --git a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js index 0bba2a2e160..da33e092086 100644 --- a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js +++ b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import axios from '../lib/utils/axios_utils'; import { s__ } from '../locale'; import Flash from '../flash'; @@ -10,7 +10,7 @@ function generateErrorBoxContent(errors) { const errorList = [].concat(errors).map( errorString => ` <li> - ${_.escape(errorString)} + ${esc(errorString)} </li> `, ); diff --git a/app/assets/javascripts/commons/jquery.js b/app/assets/javascripts/commons/jquery.js index 2f268419bff..25640f71af2 100644 --- a/app/assets/javascripts/commons/jquery.js +++ b/app/assets/javascripts/commons/jquery.js @@ -4,6 +4,6 @@ import 'jquery'; import 'jquery-ujs'; import 'vendor/jquery.endless-scroll'; import 'jquery.caret'; // must be imported before at.js -import 'at.js'; +import '@gitlab/at.js'; import 'vendor/jquery.scrollTo'; import 'jquery.waitforimages'; diff --git a/app/assets/javascripts/contributors/components/contributors.vue b/app/assets/javascripts/contributors/components/contributors.vue index caad2a835fa..8dbf0a68c43 100644 --- a/app/assets/javascripts/contributors/components/contributors.vue +++ b/app/assets/javascripts/contributors/components/contributors.vue @@ -1,5 +1,5 @@ <script> -import _ from 'underscore'; +import { debounce, uniq } from 'lodash'; import { mapActions, mapState, mapGetters } from 'vuex'; import { GlLoadingIcon } from '@gitlab/ui'; import { GlAreaChart } from '@gitlab/ui/dist/charts'; @@ -120,7 +120,7 @@ export default { return this.xAxisRange[this.xAxisRange.length - 1]; }, charts() { - return _.uniq(this.individualCharts); + return uniq(this.individualCharts); }, }, mounted() { @@ -171,7 +171,7 @@ export default { }); }) .catch(() => {}); - this.masterChart.on('datazoom', _.debounce(this.setIndividualChartsZoom, 200)); + this.masterChart.on('datazoom', debounce(this.setIndividualChartsZoom, 200)); }, onIndividualChartCreated(chart) { this.individualCharts.push(chart); diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js index c762e298eb8..6f486e1a539 100644 --- a/app/assets/javascripts/gfm_auto_complete.js +++ b/app/assets/javascripts/gfm_auto_complete.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import 'at.js'; +import '@gitlab/at.js'; import _ from 'underscore'; import SidebarMediator from '~/sidebar/sidebar_mediator'; import glRegexp from './lib/utils/regexp'; diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue index 163849d3c40..797aa15a2b9 100644 --- a/app/assets/javascripts/jobs/components/environments_block.vue +++ b/app/assets/javascripts/jobs/components/environments_block.vue @@ -12,6 +12,11 @@ export default { type: Object, required: true, }, + deploymentCluster: { + type: Object, + required: false, + default: null, + }, iconStatus: { type: Object, required: true, @@ -61,14 +66,14 @@ export default { : ''; }, hasCluster() { - return this.hasLastDeployment && this.lastDeployment.cluster; + return Boolean(this.deploymentCluster) && Boolean(this.deploymentCluster.name); }, clusterNameOrLink() { if (!this.hasCluster) { return ''; } - const { name, path } = this.lastDeployment.cluster; + const { name, path } = this.deploymentCluster; const escapedName = _.escape(name); const escapedPath = _.escape(path); @@ -86,6 +91,9 @@ export default { false, ); }, + kubernetesNamespace() { + return this.hasCluster ? this.deploymentCluster.kubernetes_namespace : null; + }, }, methods: { deploymentLink(name) { @@ -109,75 +117,153 @@ export default { ); }, lastEnvironmentMessage() { - const { environmentLink, clusterNameOrLink, hasCluster } = this; - - const message = hasCluster - ? __('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.') - : __('This job is deployed to %{environmentLink}.'); - - return sprintf(message, { environmentLink, clusterNameOrLink }, false); + const { environmentLink, clusterNameOrLink, hasCluster, kubernetesNamespace } = this; + if (hasCluster) { + if (kubernetesNamespace) { + return sprintf( + __( + 'This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', + ), + { environmentLink, clusterNameOrLink, kubernetesNamespace }, + false, + ); + } + // we know the cluster but not the namespace + return sprintf( + __('This job is deployed to %{environmentLink} using cluster %{clusterNameOrLink}.'), + { environmentLink, clusterNameOrLink }, + false, + ); + } + // not a cluster deployment + return sprintf(__('This job is deployed to %{environmentLink}.'), { environmentLink }, false); }, outOfDateEnvironmentMessage() { - const { hasLastDeployment, hasCluster, environmentLink, clusterNameOrLink } = this; + const { + hasLastDeployment, + hasCluster, + environmentLink, + clusterNameOrLink, + kubernetesNamespace, + } = this; if (hasLastDeployment) { - const message = hasCluster - ? __( - 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.', - ) - : __( - 'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.', + const deploymentLink = this.deploymentLink(__('most recent deployment')); + if (hasCluster) { + if (kubernetesNamespace) { + return sprintf( + __( + 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. View the %{deploymentLink}.', + ), + { environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink }, + false, ); - + } + // we know the cluster but not the namespace + return sprintf( + __( + 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}. View the %{deploymentLink}.', + ), + { environmentLink, clusterNameOrLink, deploymentLink }, + false, + ); + } + // not a cluster deployment return sprintf( - message, - { - environmentLink, - clusterNameOrLink, - deploymentLink: this.deploymentLink(__('most recent deployment')), - }, + __( + 'This job is an out-of-date deployment to %{environmentLink}. View the %{deploymentLink}.', + ), + { environmentLink, deploymentLink }, false, ); } - - const message = hasCluster - ? __( + // no last deployment, i.e. this is the first deployment + if (hasCluster) { + if (kubernetesNamespace) { + return sprintf( + __( + 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', + ), + { environmentLink, clusterNameOrLink, kubernetesNamespace }, + false, + ); + } + // we know the cluster but not the namespace + return sprintf( + __( 'This job is an out-of-date deployment to %{environmentLink} using cluster %{clusterNameOrLink}.', - ) - : __('This job is an out-of-date deployment to %{environmentLink}.'); - + ), + { environmentLink, clusterNameOrLink }, + false, + ); + } + // not a cluster deployment return sprintf( - message, - { - environmentLink, - clusterNameOrLink, - }, + __('This job is an out-of-date deployment to %{environmentLink}.'), + { environmentLink }, false, ); }, creatingEnvironmentMessage() { - const { hasLastDeployment, hasCluster, environmentLink, clusterNameOrLink } = this; + const { + hasLastDeployment, + hasCluster, + environmentLink, + clusterNameOrLink, + kubernetesNamespace, + } = this; if (hasLastDeployment) { - const message = hasCluster - ? __( - 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.', - ) - : __( - 'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.', + const deploymentLink = this.deploymentLink(__('latest deployment')); + if (hasCluster) { + if (kubernetesNamespace) { + return sprintf( + __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}. This will overwrite the %{deploymentLink}.', + ), + { environmentLink, clusterNameOrLink, kubernetesNamespace, deploymentLink }, + false, ); - + } + // we know the cluster but not the namespace + return sprintf( + __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}. This will overwrite the %{deploymentLink}.', + ), + { environmentLink, clusterNameOrLink, deploymentLink }, + false, + ); + } + // not a cluster deployment return sprintf( - message, - { - environmentLink, - clusterNameOrLink, - deploymentLink: this.deploymentLink(__('latest deployment')), - }, + __( + 'This job is creating a deployment to %{environmentLink}. This will overwrite the %{deploymentLink}.', + ), + { environmentLink, deploymentLink }, false, ); } - + // no last deployment, i.e. this is the first deployment + if (hasCluster) { + if (kubernetesNamespace) { + return sprintf( + __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink} and namespace %{kubernetesNamespace}.', + ), + { environmentLink, clusterNameOrLink, kubernetesNamespace }, + false, + ); + } + // we know the cluster but not the namespace + return sprintf( + __( + 'This job is creating a deployment to %{environmentLink} using cluster %{clusterNameOrLink}.', + ), + { environmentLink, clusterNameOrLink }, + false, + ); + } + // not a cluster deployment return sprintf( __('This job is creating a deployment to %{environmentLink}.'), { environmentLink }, diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue index 0ca13e897f3..bc310f77a58 100644 --- a/app/assets/javascripts/jobs/components/job_app.vue +++ b/app/assets/javascripts/jobs/components/job_app.vue @@ -256,6 +256,7 @@ export default { v-if="hasEnvironment" class="js-job-environment" :deployment-status="job.deployment_status" + :deployment-cluster="job.deployment_cluster" :icon-status="job.status" /> diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index c01024fc2cd..b3b189c1114 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -15,7 +15,7 @@ import { escape, uniqueId } from 'lodash'; import Cookies from 'js-cookie'; import Autosize from 'autosize'; import 'jquery.caret'; // required by at.js -import 'at.js'; +import '@gitlab/at.js'; import Vue from 'vue'; import { GlSkeletonLoading } from '@gitlab/ui'; import AjaxCache from '~/lib/utils/ajax_cache'; diff --git a/app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js b/app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js index 9a1bc46bf4a..95f4ba28b42 100644 --- a/app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js +++ b/app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js @@ -26,18 +26,18 @@ export default class UsagePingPayload { requestPayload() { if (this.isInserted) return this.showPayload(); - this.spinner.classList.add('d-inline'); + this.spinner.classList.add('d-inline-flex'); return axios .get(this.container.dataset.endpoint, { responseType: 'text', }) .then(({ data }) => { - this.spinner.classList.remove('d-inline'); + this.spinner.classList.remove('d-inline-flex'); this.insertPayload(data); }) .catch(() => { - this.spinner.classList.remove('d-inline'); + this.spinner.classList.remove('d-inline-flex'); flash(__('Error fetching usage ping data.')); }); } diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index e98030f1511..657e52674db 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -11,7 +11,7 @@ // like a table or typography then make changes in the framework/ directory. // If you need to add unique style that should affect only one page - use pages/ // directory. -@import "at.js/dist/css/jquery.atwho"; +@import "@gitlab/at.js/dist/css/jquery.atwho"; @import "dropzone/dist/basic"; @import "select2/select2"; diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index bd0134a82d3..a8244219b10 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -63,7 +63,8 @@ display: block; } - .select2-choices { + .select2-choices, + .select2-choice { border-color: $red-500; } } diff --git a/app/assets/stylesheets/framework/spinner.scss b/app/assets/stylesheets/framework/spinner.scss index 91fe75075dc..5e05311041c 100644 --- a/app/assets/stylesheets/framework/spinner.scss +++ b/app/assets/stylesheets/framework/spinner.scss @@ -49,3 +49,9 @@ @include spinner-color($white); } } + +.btn { + .spinner { + vertical-align: text-bottom; + } +} diff --git a/app/models/deployment.rb b/app/models/deployment.rb index 5450357fe1b..68f50b13a07 100644 --- a/app/models/deployment.rb +++ b/app/models/deployment.rb @@ -30,6 +30,7 @@ class Deployment < ApplicationRecord validate :valid_ref, on: :create delegate :name, to: :environment, prefix: true + delegate :kubernetes_namespace, to: :deployment_cluster, allow_nil: true scope :for_environment, -> (environment) { where(environment_id: environment) } scope :for_environment_name, -> (name) do diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb index 0ef71ff8af5..fe6afa4ff6f 100644 --- a/app/serializers/build_details_entity.rb +++ b/app/serializers/build_details_entity.rb @@ -22,6 +22,12 @@ class BuildDetailsEntity < JobEntity end end + expose :deployment_cluster, if: -> (build) { build&.deployment&.cluster } do |build, options| + # Until data is copied over from deployments.cluster_id, this entity must represent Deployment instead of DeploymentCluster + # https://gitlab.com/gitlab-org/gitlab/issues/202628 + DeploymentClusterEntity.represent(build.deployment, options) + end + expose :artifact, if: -> (*) { can?(current_user, :read_build, build) } do expose :download_path, if: -> (*) { build.artifacts? } do |build| download_project_job_artifacts_path(project, build) diff --git a/app/serializers/cluster_basic_entity.rb b/app/serializers/cluster_basic_entity.rb deleted file mode 100644 index d104f2c8bbd..00000000000 --- a/app/serializers/cluster_basic_entity.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true - -class ClusterBasicEntity < Grape::Entity - include RequestAwareEntity - - expose :name - expose :path, if: -> (cluster) { can?(request.current_user, :read_cluster, cluster) } do |cluster| - cluster.present(current_user: request.current_user).show_path - end -end diff --git a/app/serializers/deployment_cluster_entity.rb b/app/serializers/deployment_cluster_entity.rb new file mode 100644 index 00000000000..98736472b62 --- /dev/null +++ b/app/serializers/deployment_cluster_entity.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class DeploymentClusterEntity < Grape::Entity + include RequestAwareEntity + + # Until data is copied over from deployments.cluster_id, this entity must represent Deployment instead of DeploymentCluster + # https://gitlab.com/gitlab-org/gitlab/issues/202628 + + expose :name do |deployment| + deployment.cluster.name + end + + expose :path, if: -> (deployment) { can?(request.current_user, :read_cluster, deployment.cluster) } do |deployment| + deployment.cluster.present(current_user: request.current_user).show_path + end + + expose :kubernetes_namespace, if: -> (deployment) { can?(request.current_user, :read_cluster, deployment.cluster) } do |deployment| + deployment.kubernetes_namespace + end +end diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb index 94773eeebd0..dc7c4654208 100644 --- a/app/serializers/deployment_entity.rb +++ b/app/serializers/deployment_entity.rb @@ -41,7 +41,11 @@ class DeploymentEntity < Grape::Entity JobEntity.represent(deployment.playable_build, options.merge(only: [:play_path, :retry_path])) end - expose :cluster, using: ClusterBasicEntity + expose :cluster do |deployment, options| + # Until data is copied over from deployments.cluster_id, this entity must represent Deployment instead of DeploymentCluster + # https://gitlab.com/gitlab-org/gitlab/issues/202628 + DeploymentClusterEntity.represent(deployment, options) unless deployment.cluster.nil? + end private diff --git a/app/views/admin/application_settings/_usage.html.haml b/app/views/admin/application_settings/_usage.html.haml index b4fe1bbf028..9421585b70c 100644 --- a/app/views/admin/application_settings/_usage.html.haml +++ b/app/views/admin/application_settings/_usage.html.haml @@ -26,7 +26,7 @@ %p.mb-2= s_('%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe } %button.btn.js-usage-ping-payload-trigger{ type: 'button' } - .js-spinner.d-none= icon('spinner spin') + .spinner.js-spinner.d-none .js-text.d-inline= _('Preview payload') %pre.usage-data.js-usage-ping-payload.js-syntax-highlight.code.highlight.mt-2.d-none{ data: { endpoint: usage_data_admin_application_settings_path(format: :html) } } - else diff --git a/app/views/shared/milestones/_delete_button.html.haml b/app/views/shared/milestones/_delete_button.html.haml index e236c24b088..e00a10398d3 100644 --- a/app/views/shared/milestones/_delete_button.html.haml +++ b/app/views/shared/milestones/_delete_button.html.haml @@ -9,6 +9,6 @@ milestone_merge_request_count: @milestone.merge_requests.count }, disabled: true } = _('Delete') - = icon('spin spinner', class: 'js-loading-icon hidden' ) + .spinner.js-loading-icon.hidden #delete-milestone-modal diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml index fbbcc4f3e68..a6fb8e6d4fc 100644 --- a/app/views/shared/milestones/_sidebar.html.haml +++ b/app/views/shared/milestones/_sidebar.html.haml @@ -98,10 +98,6 @@ human_time_estimate: @milestone.human_total_issue_time_estimate, human_time_spent: @milestone.human_total_issue_time_spent, limit_to_hours: Gitlab::CurrentSettings.time_tracking_limit_to_hours.to_s } } - // Fallback while content is loading - .title.hide-collapsed - = _('Time tracking') - = icon('spinner spin') = render_if_exists 'shared/milestones/weight', milestone: milestone diff --git a/app/views/shared/milestones/_tab_loading.html.haml b/app/views/shared/milestones/_tab_loading.html.haml index 68458c2d0aa..dfca6a184be 100644 --- a/app/views/shared/milestones/_tab_loading.html.haml +++ b/app/views/shared/milestones/_tab_loading.html.haml @@ -1,2 +1,2 @@ .text-center.prepend-top-default - = icon('spin spinner 2x', 'aria-hidden': 'true', 'aria-label': 'Loading tab content') + .spinner.spinner-md |