diff options
Diffstat (limited to 'app')
23 files changed, 113 insertions, 140 deletions
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue index 09ec385bbba..2599d1c80b8 100644 --- a/app/assets/javascripts/boards/components/board_filtered_search.vue +++ b/app/assets/javascripts/boards/components/board_filtered_search.vue @@ -6,6 +6,7 @@ import { updateHistory, setUrlParams } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants'; import FilteredSearch from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; +import { AssigneeFilterType } from '~/boards/constants'; export default { i18n: { @@ -37,6 +38,7 @@ export default { authorUsername, labelName, assigneeUsername, + assigneeId, search, milestoneTitle, iterationId, @@ -63,6 +65,13 @@ export default { }); } + if (assigneeId) { + filteredSearchValue.push({ + type: 'assignee', + value: { data: assigneeId, operator: '=' }, + }); + } + if (types) { filteredSearchValue.push({ type: 'type', @@ -211,6 +220,7 @@ export default { authorUsername, labelName, assigneeUsername, + assigneeId, search, milestoneTitle, types, @@ -246,6 +256,7 @@ export default { author_username: authorUsername, 'label_name[]': labelName, assignee_username: assigneeUsername, + assignee_id: assigneeId, milestone_title: milestoneTitle, iteration_id: iterationId, search, @@ -295,7 +306,11 @@ export default { filterParams.authorUsername = filter.value.data; break; case 'assignee': - filterParams.assigneeUsername = filter.value.data; + if (Object.values(AssigneeFilterType).includes(filter.value.data)) { + filterParams.assigneeId = filter.value.data; + } else { + filterParams.assigneeUsername = filter.value.data; + } break; case 'type': filterParams.types = filter.value.data; diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js index 80559795cf0..e0eea761b31 100644 --- a/app/assets/javascripts/boards/constants.js +++ b/app/assets/javascripts/boards/constants.js @@ -120,6 +120,7 @@ export const FilterFields = { /* eslint-disable @gitlab/require-i18n-strings */ export const AssigneeFilterType = { any: 'Any', + none: 'None', }; export const MilestoneFilterType = { diff --git a/app/assets/javascripts/cycle_analytics/components/path_navigation.vue b/app/assets/javascripts/cycle_analytics/components/path_navigation.vue index f8f89772fd6..af7334ecf2e 100644 --- a/app/assets/javascripts/cycle_analytics/components/path_navigation.vue +++ b/app/assets/javascripts/cycle_analytics/components/path_navigation.vue @@ -57,7 +57,7 @@ export default { }; </script> <template> - <gl-skeleton-loading v-if="loading" :lines="2" class="h-auto pt-2 pb-1" /> + <gl-skeleton-loading v-if="loading" :lines="2" /> <gl-path v-else :key="selectedStage.id" :items="stages" @selected="onSelectStage"> <template #default="{ pathItem, pathId }"> <gl-popover diff --git a/app/assets/javascripts/cycle_analytics/components/value_stream_filters.vue b/app/assets/javascripts/cycle_analytics/components/value_stream_filters.vue index 8610dfc2b03..64461797c46 100644 --- a/app/assets/javascripts/cycle_analytics/components/value_stream_filters.vue +++ b/app/assets/javascripts/cycle_analytics/components/value_stream_filters.vue @@ -59,7 +59,9 @@ export default { }; </script> <template> - <div class="gl-mt-3 gl-py-2 gl-px-3 bg-gray-light border-top border-bottom"> + <div + class="gl-mt-3 gl-py-2 gl-px-3 gl-bg-gray-10 gl-border-b-1 gl-border-b-solid gl-border-t-1 gl-border-t-solid gl-border-gray-100" + > <filter-bar data-testid="vsa-filter-bar" class="filtered-search-box gl-display-flex gl-mb-2 gl-mr-3 gl-border-none" diff --git a/app/assets/javascripts/experimental_flags.js b/app/assets/javascripts/experimental_flags.js deleted file mode 100644 index 1d60847147b..00000000000 --- a/app/assets/javascripts/experimental_flags.js +++ /dev/null @@ -1,15 +0,0 @@ -import $ from 'jquery'; -import Cookies from 'js-cookie'; - -export default () => { - $('.js-experiment-feature-toggle').on('change', (e) => { - const el = e.target; - - Cookies.set(el.name, el.value, { - expires: 365 * 10, - }); - - document.body.scrollTop = 0; - window.location.reload(); - }); -}; diff --git a/app/assets/javascripts/jobs/bridge/components/sidebar.vue b/app/assets/javascripts/jobs/bridge/components/sidebar.vue index 34cefb0d0e2..3ba07cf55d1 100644 --- a/app/assets/javascripts/jobs/bridge/components/sidebar.vue +++ b/app/assets/javascripts/jobs/bridge/components/sidebar.vue @@ -8,7 +8,6 @@ import CommitBlock from '../../components/commit_block.vue'; export default { styles: { - top: '75px', width: '290px', }, name: 'BridgeSidebar', @@ -37,17 +36,37 @@ export default { required: true, }, }, + data() { + return { + topPosition: 0, + }; + }, + computed: { + rootStyle() { + return { ...this.$options.styles, top: `${this.topPosition}px` }; + }, + }, + mounted() { + this.setTopPosition(); + }, methods: { onSidebarButtonClick() { this.$emit('toggleSidebar'); }, + setTopPosition() { + const navbarEl = document.querySelector('.js-navbar'); + + if (navbarEl) { + this.topPosition = navbarEl.getBoundingClientRect().bottom; + } + }, }, }; </script> <template> <aside class="gl-fixed gl-right-0 gl-px-5 gl-bg-gray-10 gl-h-full gl-border-l-solid gl-border-1 gl-border-gray-100 gl-z-index-200 gl-overflow-hidden" - :style="this.$options.styles" + :style="rootStyle" > <div class="gl-py-5 gl-display-flex gl-align-items-center"> <tooltip-on-truncate :title="bridgeJob.name" truncate-target="child" diff --git a/app/assets/javascripts/pages/admin/runners/edit/index.js b/app/assets/javascripts/pages/admin/runners/edit/index.js index d1853772fda..ddf135a2732 100644 --- a/app/assets/javascripts/pages/admin/runners/edit/index.js +++ b/app/assets/javascripts/pages/admin/runners/edit/index.js @@ -1,3 +1,3 @@ -import { initRunnerDetail } from '~/runner/runner_details'; +import { initAdminRunnerEdit } from '~/runner/admin_runner_edit'; -initRunnerDetail(); +initAdminRunnerEdit(); diff --git a/app/assets/javascripts/runner/runner_details/runner_details_app.vue b/app/assets/javascripts/runner/admin_runner_edit/admin_runner_edit_app.vue index f0a1d781a3a..4d2ca9b0c58 100644 --- a/app/assets/javascripts/runner/runner_details/runner_details_app.vue +++ b/app/assets/javascripts/runner/admin_runner_edit/admin_runner_edit_app.vue @@ -9,7 +9,7 @@ import getRunnerQuery from '../graphql/get_runner.query.graphql'; import { captureException } from '../sentry_utils'; export default { - name: 'RunnerDetailsApp', + name: 'AdminRunnerEditApp', components: { RunnerHeader, RunnerUpdateForm, diff --git a/app/assets/javascripts/runner/runner_details/index.js b/app/assets/javascripts/runner/admin_runner_edit/index.js index db8f239a3c3..adb420f9963 100644 --- a/app/assets/javascripts/runner/runner_details/index.js +++ b/app/assets/javascripts/runner/admin_runner_edit/index.js @@ -1,11 +1,11 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; -import RunnerDetailsApp from './runner_details_app.vue'; +import AdminRunnerEditApp from './admin_runner_edit_app.vue'; Vue.use(VueApollo); -export const initRunnerDetail = (selector = '#js-runner-details') => { +export const initAdminRunnerEdit = (selector = '#js-admin-runner-edit') => { const el = document.querySelector(selector); if (!el) { @@ -22,7 +22,7 @@ export const initRunnerDetail = (selector = '#js-runner-details') => { el, apolloProvider, render(h) { - return h(RunnerDetailsApp, { + return h(AdminRunnerEditApp, { props: { runnerId, }, diff --git a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue index 82ee41d6def..0934508c87f 100644 --- a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue +++ b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue @@ -162,9 +162,9 @@ export default { See https://gitlab.com/gitlab-org/gitlab/-/issues/334802 --> <gl-button - v-if="canUpdate && runner.adminUrl" + v-if="canUpdate && runner.editAdminUrl" v-gl-tooltip.hover.viewport="$options.I18N_EDIT" - :href="runner.adminUrl" + :href="runner.editAdminUrl" :aria-label="$options.I18N_EDIT" icon="pencil" data-testid="edit-runner" diff --git a/app/assets/javascripts/runner/components/runner_update_form.vue b/app/assets/javascripts/runner/components/runner_update_form.vue index aeb5869bcce..e3deb94236e 100644 --- a/app/assets/javascripts/runner/components/runner_update_form.vue +++ b/app/assets/javascripts/runner/components/runner_update_form.vue @@ -10,7 +10,7 @@ import { import { modelToUpdateMutationVariables, runnerToModel, -} from 'ee_else_ce/runner/runner_details/runner_update_form_utils'; +} from 'ee_else_ce/runner/runner_update_form_utils'; import { createAlert, VARIANT_SUCCESS } from '~/flash'; import { __ } from '~/locale'; import { captureException } from '~/runner/sentry_utils'; diff --git a/app/assets/javascripts/runner/graphql/get_runners.query.graphql b/app/assets/javascripts/runner/graphql/get_runners.query.graphql index 51a91b9eb96..05df399fa6a 100644 --- a/app/assets/javascripts/runner/graphql/get_runners.query.graphql +++ b/app/assets/javascripts/runner/graphql/get_runners.query.graphql @@ -26,6 +26,7 @@ query getRunners( nodes { ...RunnerNode adminUrl + editAdminUrl } pageInfo { ...PageInfo diff --git a/app/assets/javascripts/runner/runner_details/runner_update_form_utils.js b/app/assets/javascripts/runner/runner_update_form_utils.js index 3b519fa7d71..3b519fa7d71 100644 --- a/app/assets/javascripts/runner/runner_details/runner_update_form_utils.js +++ b/app/assets/javascripts/runner/runner_update_form_utils.js diff --git a/app/assets/javascripts/tree.js b/app/assets/javascripts/tree.js deleted file mode 100644 index 58bff370fa5..00000000000 --- a/app/assets/javascripts/tree.js +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable func-names, consistent-return, one-var, class-methods-use-this */ - -import $ from 'jquery'; -import { visitUrl } from './lib/utils/url_utility'; - -export default class TreeView { - constructor() { - this.initKeyNav(); - // Code browser tree slider - // Make the entire tree-item row clickable, but not if clicking another link (like a commit message) - $('.tree-content-holder .tree-item').on('click', function (e) { - const $clickedEl = $(e.target); - const path = $('.tree-item-file-name a', this).attr('href'); - if (!$clickedEl.is('a') && !$clickedEl.is('.str-truncated')) { - if (e.metaKey || e.which === 2) { - e.preventDefault(); - return window.open(path, '_blank'); - } - return visitUrl(path); - } - }); - // Show the "Loading commit data" for only the first element - $('span.log_loading').first().removeClass('hide'); - } - - initKeyNav() { - const li = $('tr.tree-item'); - let liSelected = null; - return $('body').keydown((e) => { - let next, path; - if ($('input:focus').length > 0 && (e.which === 38 || e.which === 40)) { - return false; - } - if (e.which === 40) { - if (liSelected) { - next = liSelected.next(); - if (next.length > 0) { - liSelected.removeClass('selected'); - liSelected = next.addClass('selected'); - } - } else { - liSelected = li.eq(0).addClass('selected'); - } - return $(liSelected).focus(); - } else if (e.which === 38) { - if (liSelected) { - next = liSelected.prev(); - if (next.length > 0) { - liSelected.removeClass('selected'); - liSelected = next.addClass('selected'); - } - } else { - liSelected = li.last().addClass('selected'); - } - return $(liSelected).focus(); - } else if (e.which === 13) { - path = $('.tree-item.selected .tree-item-file-name a').attr('href'); - if (path) { - return visitUrl(path); - } - } - }); - } -} diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue index 06478a89721..b70317b2ec4 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue @@ -4,7 +4,7 @@ import { compact } from 'lodash'; import createFlash from '~/flash'; import { __ } from '~/locale'; -import { DEFAULT_LABEL_ANY } from '../constants'; +import { DEFAULT_NONE_ANY } from '../constants'; import BaseToken from './base_token.vue'; @@ -36,7 +36,7 @@ export default { }, computed: { defaultAuthors() { - return this.config.defaultAuthors || [DEFAULT_LABEL_ANY]; + return this.config.defaultAuthors || DEFAULT_NONE_ANY; }, preloadedAuthors() { return this.config.preloadedAuthors || []; diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index 43d74603407..16657612050 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -15,7 +15,7 @@ class Admin::RunnersController < Admin::ApplicationController # future iterations. For now, this route will have a # redirect until this new view is developed. See more: # https://gitlab.com/gitlab-org/gitlab/-/issues/347856 - redirect_to edit_admin_runner_path(runner) + redirect_to edit_admin_runner_path(runner) unless Feature.enabled?(:runner_read_only_admin_view, default_enabled: :yaml) end def edit diff --git a/app/controllers/projects/security/configuration_controller.rb b/app/controllers/projects/security/configuration_controller.rb index 444f4783a19..14f765814e6 100644 --- a/app/controllers/projects/security/configuration_controller.rb +++ b/app/controllers/projects/security/configuration_controller.rb @@ -9,6 +9,37 @@ module Projects def show render_403 unless can?(current_user, :read_security_configuration, project) + + respond_to do |format| + format.html + format.json do + render status: :ok, json: configuration.to_h + end + end + end + + private + + def configuration + if unify_configuration_enabled? + configuration_presenter + else + {} + end + end + + def configuration_presenter + ::Projects::Security::ConfigurationPresenter.new(project, + **presenter_attributes, + current_user: current_user) + end + + def presenter_attributes + {} + end + + def unify_configuration_enabled? + Feature.enabled?(:unify_security_configuration, project, default_enabled: :yaml) end end end diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb index f382b3624ed..2cf95ac0dae 100644 --- a/app/models/concerns/routable.rb +++ b/app/models/concerns/routable.rb @@ -190,5 +190,10 @@ module Routable route || build_route(source: self) route.path = build_full_path route.name = build_full_name + route.namespace = if is_a?(Namespace) + self + elsif is_a?(Project) + self.project_namespace + end end end diff --git a/app/models/email.rb b/app/models/email.rb index cda46c5e523..3896dfd5d22 100644 --- a/app/models/email.rb +++ b/app/models/email.rb @@ -6,8 +6,8 @@ class Email < ApplicationRecord belongs_to :user, optional: false - validates :email, presence: true, uniqueness: true - validate :validate_email_format + validates :email, presence: true, uniqueness: true, devise_email: true + validate :unique_email, if: ->(email) { email.email_changed? } scope :confirmed, -> { where.not(confirmed_at: nil) } @@ -33,10 +33,6 @@ class Email < ApplicationRecord self.errors.add(:email, 'has already been taken') if primary_email_of_another_user? end - def validate_email_format - self.errors.add(:email, I18n.t(:invalid, scope: 'valid_email.validations.email')) unless ValidateEmail.valid?(self.email) - end - # once email is confirmed, update the gpg signatures def update_invalid_gpg_signatures user.update_invalid_gpg_signatures if confirmed? diff --git a/app/models/namespace.rb b/app/models/namespace.rb index adf42acdd2b..1e7f0f10aa6 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -43,7 +43,7 @@ class Namespace < ApplicationRecord has_many :projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :project_statistics has_one :namespace_settings, inverse_of: :namespace, class_name: 'NamespaceSetting', autosave: true - has_one :namespace_route, foreign_key: :namespace_id, autosave: true, inverse_of: :namespace, class_name: 'Route' + has_one :namespace_route, foreign_key: :namespace_id, autosave: false, inverse_of: :namespace, class_name: 'Route' has_many :runner_namespaces, inverse_of: :namespace, class_name: 'Ci::RunnerNamespace' has_many :runners, through: :runner_namespaces, source: :runner, class_name: 'Ci::Runner' diff --git a/app/views/admin/runners/edit.html.haml b/app/views/admin/runners/edit.html.haml index 12d0f6a9d18..3f5c868d768 100644 --- a/app/views/admin/runners/edit.html.haml +++ b/app/views/admin/runners/edit.html.haml @@ -1,11 +1,16 @@ - add_page_specific_style 'page_bundles/ci_status' -- title = "##{@runner.id} (#{@runner.short_sha})" -- breadcrumb_title title -- page_title title -- add_to_breadcrumbs _('Runners'), admin_runners_path +- runner_name = "##{@runner.id} (#{@runner.short_sha})" +- if Feature.enabled?(:runner_read_only_admin_view) + - breadcrumb_title _('Edit') + - page_title _('Edit'), runner_name + - add_to_breadcrumbs _('Runners'), admin_runners_path + - add_to_breadcrumbs runner_name, admin_runner_path(@runner) +- else + - breadcrumb_title runner_name + - page_title runner_name -#js-runner-details{ data: {runner_id: @runner.id} } +#js-admin-runner-edit{ data: {runner_id: @runner.id} } .row .col-md-6 diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml new file mode 100644 index 00000000000..7b4390ae463 --- /dev/null +++ b/app/views/admin/runners/show.html.haml @@ -0,0 +1,8 @@ +- add_page_specific_style 'page_bundles/ci_status' + +- title = "##{@runner.id} (#{@runner.short_sha})" +- breadcrumb_title title +- page_title title +- add_to_breadcrumbs _('Runners'), admin_runners_path + +-# Empty view in development behind feature flag runner_read_only_admin_view diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb index 321d492f0f3..54689df4d7b 100644 --- a/app/workers/email_receiver_worker.rb +++ b/app/workers/email_receiver_worker.rb @@ -90,37 +90,6 @@ class EmailReceiverWorker # rubocop:disable Scalability/IdempotentWorker def handle_failure(error) return unless raw.present? - can_retry = false - reason = - case error - when Gitlab::Email::UnknownIncomingEmail - s_("EmailError|We couldn't figure out what the email is for. Please create your issue or comment through the web interface.") - when Gitlab::Email::SentNotificationNotFoundError - s_("EmailError|We couldn't figure out what the email is in reply to. Please create your comment through the web interface.") - when Gitlab::Email::ProjectNotFound - s_("EmailError|We couldn't find the project. Please check if there's any typo.") - when Gitlab::Email::EmptyEmailError - can_retry = true - s_("EmailError|It appears that the email is blank. Make sure your reply is at the top of the email, we can't process inline replies.") - when Gitlab::Email::UserNotFoundError - s_("EmailError|We couldn't figure out what user corresponds to the email. Please create your comment through the web interface.") - when Gitlab::Email::UserBlockedError - s_("EmailError|Your account has been blocked. If you believe this is in error, contact a staff member.") - when Gitlab::Email::UserNotAuthorizedError - s_("EmailError|You are not allowed to perform this action. If you believe this is in error, contact a staff member.") - when Gitlab::Email::NoteableNotFoundError - s_("EmailError|The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member.") - when Gitlab::Email::InvalidAttachment - error.message - when Gitlab::Email::InvalidRecordError - can_retry = true - error.message - end - - if reason - receiver.mail.body = nil - - EmailRejectionMailer.rejection(reason, receiver.mail.encoded, can_retry).deliver_later - end + Gitlab::Email::FailureHandler.handle(receiver, error) end end |
