diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-28 15:10:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-08-28 15:10:42 +0300 |
commit | 62a3deaa9f6e1e1986c43b49a41a917201ec2734 (patch) | |
tree | ce1e28b7a44c24da614253173c58dc50f161ee94 /app | |
parent | 603425e1f4ca8678398278e18b68889fc00c90dc (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
49 files changed, 291 insertions, 335 deletions
diff --git a/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue b/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue index 11593fa355a..dbf1dfe7a29 100644 --- a/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue +++ b/app/assets/javascripts/jobs/components/table/cells/duration_cell.vue @@ -27,6 +27,9 @@ export default { durationFormatted() { return formatTime(this.duration * 1000); }, + hasDurationAndFinishedTime() { + return this.finishedTime && this.duration; + }, }, }; </script> @@ -37,7 +40,11 @@ export default { <gl-icon name="timer" :size="$options.iconSize" data-testid="duration-icon" /> {{ durationFormatted }} </div> - <div v-if="finishedTime" data-testid="job-finished-time"> + <div + v-if="finishedTime" + :class="{ 'gl-mt-2': hasDurationAndFinishedTime }" + data-testid="job-finished-time" + > <gl-icon name="calendar" :size="$options.iconSize" data-testid="finished-time-icon" /> <time-ago-tooltip :time="finishedTime" /> </div> diff --git a/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue b/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue index 1a6d1a341b0..c8f0fdd4439 100644 --- a/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue +++ b/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue @@ -41,7 +41,7 @@ export default { {{ pipelineId }} </gl-link> </div> - <div> + <div class="gl-font-sm gl-text-secondary gl-mt-2"> <span>{{ __('created by') }}</span> <gl-link v-if="showAvatar" :href="userPath" data-testid="pipeline-user-link"> <gl-avatar :src="pipelineUserAvatar" :size="16" /> diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index a009f2975bb..1a4add30f9f 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -210,8 +210,6 @@ export default { methods: { ...mapActions([ 'saveNote', - 'stopPolling', - 'restartPolling', 'removePlaceholderNotes', 'closeIssuable', 'reopenIssuable', @@ -253,7 +251,6 @@ export default { } this.note = ''; // Empty textarea while being requested. Repopulate in catch - this.stopPolling(); this.isSubmitting = true; @@ -264,7 +261,6 @@ export default { this.saveNote(noteData) .then(() => { - this.restartPolling(); this.discard(); if (withIssueAction) { diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index 6fb958e810b..2524b9efdb6 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -169,7 +169,6 @@ export default { }); }, beforeDestroy() { - this.stopPolling(); window.removeEventListener('hashchange', this.handleHashChanged); eventHub.$off('notesApp.updateIssuableConfidentiality', this.setConfidentiality); }, @@ -182,7 +181,6 @@ export default { 'expandDiscussion', 'startTaskList', 'convertToDiscussion', - 'stopPolling', 'setConfidentiality', 'fetchNotes', ]), diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 0444eca9aa7..a20bce2e53a 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -1,5 +1,4 @@ import $ from 'jquery'; -import Visibility from 'visibilityjs'; import Vue from 'vue'; import actionCable from '~/actioncable_consumer'; import Api from '~/api'; @@ -14,8 +13,6 @@ import updateIssueLockMutation from '~/sidebar/queries/update_issue_lock.mutatio import updateMergeRequestLockMutation from '~/sidebar/queries/update_merge_request_lock.mutation.graphql'; import loadAwardsHandler from '~/awards_handler'; import { isInViewport, scrollToElement, isInMRPage } from '~/lib/utils/common_utils'; -import Poll from '~/lib/utils/poll'; -import { create } from '~/lib/utils/recurrence'; import { mergeUrlParams } from '~/lib/utils/url_utility'; import sidebarTimeTrackingEventHub from '~/sidebar/event_hub'; import TaskList from '~/task_list'; @@ -30,9 +27,6 @@ import * as constants from '../constants'; import * as types from './mutation_types'; import * as utils from './utils'; -const NOTES_POLLING_INTERVAL = 6000; -let eTagPoll; - export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) => { const { iid, targetType } = getters.getNoteableData; @@ -152,29 +146,25 @@ export const initPolling = ({ state, dispatch, getters, commit }) => { dispatch('setLastFetchedAt', getters.getNotesDataByProp('lastFetchedAt')); - if (gon.features?.actionCableNotes) { - actionCable.subscriptions.create( - { - channel: 'Noteable::NotesChannel', - project_id: state.notesData.projectId, - group_id: state.notesData.groupId, - noteable_type: state.notesData.noteableType, - noteable_id: state.notesData.noteableId, + actionCable.subscriptions.create( + { + channel: 'Noteable::NotesChannel', + project_id: state.notesData.projectId, + group_id: state.notesData.groupId, + noteable_type: state.notesData.noteableType, + noteable_id: state.notesData.noteableId, + }, + { + connected() { + dispatch('fetchUpdatedNotes'); }, - { - connected() { + received(data) { + if (data.event === 'updated') { dispatch('fetchUpdatedNotes'); - }, - received(data) { - if (data.event === 'updated') { - dispatch('fetchUpdatedNotes'); - } - }, + } }, - ); - } else { - dispatch('poll'); - } + }, + ); commit(types.SET_IS_POLLING_INITIALIZED, true); }; @@ -515,8 +505,6 @@ export const saveNote = ({ commit, dispatch }, noteData) => { {"commands_changes":{},"valid":false,"errors":{"commands_only":["Commands applied"]}} */ if (hasQuickActions && message) { - if (eTagPoll) eTagPoll.makeRequest(); - // synchronizing the quick action with the sidebar widget // this is a temporary solution until we have confidentiality real-time updates if ( @@ -624,69 +612,7 @@ export const fetchUpdatedNotes = ({ commit, state, getters, dispatch }) => { .then(({ data }) => { pollSuccessCallBack(data, commit, state, getters, dispatch); }) - .catch(() => { - createAlert({ - message: __('Something went wrong while fetching latest comments.'), - }); - }); -}; - -export const poll = ({ commit, state, getters, dispatch }) => { - const notePollOccurrenceTracking = create(); - let alert; - - notePollOccurrenceTracking.handle(1, () => { - // Since polling halts internally after 1 failure, we manually try one more time - setTimeout(() => eTagPoll.restart(), NOTES_POLLING_INTERVAL); - }); - notePollOccurrenceTracking.handle(2, () => { - // On the second failure in a row, show the alert and try one more time (hoping to succeed and clear the error) - alert = createAlert({ - message: __('Something went wrong while fetching latest comments.'), - }); - setTimeout(() => eTagPoll.restart(), NOTES_POLLING_INTERVAL); - }); - - eTagPoll = new Poll({ - resource: { - poll: () => { - const { endpoint, options } = getFetchDataParams(state); - return axios.get(endpoint, options); - }, - }, - method: 'poll', - successCallback: ({ data }) => { - pollSuccessCallBack(data, commit, state, getters, dispatch); - - if (notePollOccurrenceTracking.count) { - notePollOccurrenceTracking.reset(); - } - alert?.dismiss(); - }, - errorCallback: () => notePollOccurrenceTracking.occur(), - }); - - if (!Visibility.hidden()) { - eTagPoll.makeDelayedRequest(2500); - } else { - eTagPoll.makeRequest(); - } - - Visibility.change(() => { - if (!Visibility.hidden()) { - eTagPoll.restart(); - } else { - eTagPoll.stop(); - } - }); -}; - -export const stopPolling = () => { - if (eTagPoll) eTagPoll.stop(); -}; - -export const restartPolling = () => { - if (eTagPoll) eTagPoll.restart(); + .catch(() => {}); }; export const toggleAward = ({ commit, getters }, { awardName, noteId }) => { @@ -766,7 +692,6 @@ export const submitSuggestion = ( dispatch('resolveDiscussion', { discussionId }).catch(() => {}); commit(types.SET_RESOLVING_DISCUSSION, true); - dispatch('stopPolling'); return Api.applySuggestion(suggestionId, message) .then(dispatchResolveDiscussion) @@ -786,7 +711,6 @@ export const submitSuggestion = ( }) .finally(() => { commit(types.SET_RESOLVING_DISCUSSION, false); - dispatch('restartPolling'); }); }; @@ -801,7 +725,6 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { message, fl commit(types.SET_APPLYING_BATCH_STATE, true); commit(types.SET_RESOLVING_DISCUSSION, true); - dispatch('stopPolling'); return Api.applySuggestionBatch(suggestionIds, message) .then(() => Promise.all(resolveAllDiscussions())) @@ -823,7 +746,6 @@ export const submitSuggestionBatch = ({ commit, dispatch, state }, { message, fl .finally(() => { commit(types.SET_APPLYING_BATCH_STATE, false); commit(types.SET_RESOLVING_DISCUSSION, false); - dispatch('restartPolling'); }); }; diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue index e18e6f7ed1a..6e0d1043502 100644 --- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue @@ -18,6 +18,8 @@ import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import TitleArea from '~/vue_shared/components/registry/title_area.vue'; import ManifestsList from '~/packages_and_registries/dependency_proxy/components/manifests_list.vue'; import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/dependency_proxy/constants'; +import { getPageParams } from '~/packages_and_registries/dependency_proxy/utils'; +import { extractPageInfo } from '~/packages_and_registries/shared/utils'; import getDependencyProxyDetailsQuery from '~/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql'; @@ -79,11 +81,15 @@ export default { }, computed: { queryVariables() { - return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE }; + return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE, ...this.pageParams }; }, pageInfo() { return this.group.dependencyProxyManifests?.pageInfo; }, + pageParams() { + const pageInfo = extractPageInfo(this.$route.query); + return getPageParams(pageInfo); + }, manifests() { return this.group.dependencyProxyManifests?.nodes ?? []; }, @@ -123,25 +129,10 @@ export default { }, methods: { fetchNextPage() { - this.fetchMore({ - first: GRAPHQL_PAGE_SIZE, - after: this.pageInfo?.endCursor, - }); + this.$router.push({ query: { after: this.pageInfo?.endCursor } }); }, fetchPreviousPage() { - this.fetchMore({ - first: null, - last: GRAPHQL_PAGE_SIZE, - before: this.pageInfo?.startCursor, - }); - }, - fetchMore(variables) { - this.$apollo.queries.group.fetchMore({ - variables: { ...this.queryVariables, ...variables }, - updateQuery(_, { fetchMoreResult }) { - return fetchMoreResult; - }, - }); + this.$router.push({ query: { before: this.pageInfo?.startCursor } }); }, async submit() { try { @@ -198,14 +189,14 @@ export default { <gl-form-input-group id="proxy-url" readonly - :value="group.dependencyProxyImagePrefix" + :value="dependencyProxyImagePrefix" select-on-click class="gl-layout-w-limited" data-testid="proxy-url" > <template #append> <clipboard-button - :text="group.dependencyProxyImagePrefix" + :text="dependencyProxyImagePrefix" :title="$options.i18n.copyImagePrefixText" /> </template> diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js index 74444d2c7ec..c115898c75b 100644 --- a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js @@ -1,8 +1,8 @@ import Vue from 'vue'; import { parseBoolean } from '~/lib/utils/common_utils'; -import app from '~/packages_and_registries/dependency_proxy/app.vue'; import { apolloProvider } from '~/packages_and_registries/dependency_proxy/graphql'; import Translate from '~/vue_shared/translate'; +import createRouter from './router'; Vue.use(Translate); @@ -11,10 +11,18 @@ export const initDependencyProxyApp = () => { if (!el) { return null; } - const { groupPath, groupId, noManifestsIllustration, canClearCache, settingsPath } = el.dataset; + const { + endpoint, + groupPath, + groupId, + noManifestsIllustration, + canClearCache, + settingsPath, + } = el.dataset; return new Vue({ el, apolloProvider, + router: createRouter(endpoint), provide: { groupPath, groupId, @@ -23,7 +31,7 @@ export const initDependencyProxyApp = () => { settingsPath, }, render(createElement) { - return createElement(app); + return createElement('router-view'); }, }); }; diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/router.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/router.js new file mode 100644 index 00000000000..087d8c189c4 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/router.js @@ -0,0 +1,14 @@ +import Vue from 'vue'; +import VueRouter from 'vue-router'; +import App from '~/packages_and_registries/dependency_proxy/app.vue'; + +Vue.use(VueRouter); + +export default function createRouter(base) { + const routes = [{ path: '/', name: 'dependencyProxyApp', component: App }]; + return new VueRouter({ + mode: 'history', + base, + routes, + }); +} diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/utils.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/utils.js new file mode 100644 index 00000000000..e6b97fac896 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/utils.js @@ -0,0 +1,24 @@ +import { GRAPHQL_PAGE_SIZE } from './constants'; + +const getNextPageParams = (cursor) => ({ + after: cursor, + first: GRAPHQL_PAGE_SIZE, +}); + +const getPreviousPageParams = (cursor) => ({ + first: null, + before: cursor, + last: GRAPHQL_PAGE_SIZE, +}); + +export const getPageParams = (pageInfo = {}) => { + if (pageInfo.before) { + return getPreviousPageParams(pageInfo.before); + } + + if (pageInfo.after) { + return getNextPageParams(pageInfo.after); + } + + return {}; +}; diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue index a5c6dc98694..8567654a89e 100644 --- a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue +++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/linked_pipelines_mini_list.vue @@ -105,7 +105,7 @@ export default { v-gl-tooltip="{ title: pipelineTooltipText(pipeline) }" :href="pipeline.path" :class="triggerButtonClass(pipeline)" - class="linked-pipeline-mini-item gl-display-inline-block gl-h-6 gl-mr-2 gl-my-2 gl-rounded-full gl-vertical-align-middle" + class="linked-pipeline-mini-item gl-display-inline-flex gl-mr-2 gl-my-2 gl-rounded-full gl-vertical-align-middle" data-testid="linked-pipeline-mini-item" > <ci-icon diff --git a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue index 02dba9ba30f..f883833f7ea 100644 --- a/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue +++ b/app/assets/javascripts/pipelines/components/pipeline_mini_graph/pipeline_stages.vue @@ -42,7 +42,7 @@ export default { <div v-for="stage in stages" :key="stage.name" - class="pipeline-mini-graph-stage-container dropdown gl-display-inline-block gl-mr-2 gl-my-2 gl-vertical-align-middle" + class="pipeline-mini-graph-stage-container dropdown gl-display-inline-flex gl-mr-2 gl-my-2 gl-vertical-align-middle" > <pipeline-stage v-if="isGraphql" diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue index 60c429459bf..c01037e9791 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/failure_widget/pipeline_failed_jobs_widget.vue @@ -91,7 +91,7 @@ export default { <template #header> <gl-button variant="link" - class="gl-text-gray-700! gl-font-weight-semibold" + class="gl-text-gray-500! gl-font-weight-semibold" @click="toggleWidget" > <gl-icon :name="iconName" /> diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue index c7d89113895..32d46a0d4af 100644 --- a/app/assets/javascripts/security_configuration/components/app.vue +++ b/app/assets/javascripts/security_configuration/components/app.vue @@ -1,13 +1,18 @@ <script> import { GlTab, GlTabs, GlSprintf, GlLink, GlAlert } from '@gitlab/ui'; +import Api from '~/api'; import { __, s__ } from '~/locale'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue'; import SectionLayout from '~/vue_shared/security_configuration/components/section_layout.vue'; import SafeHtml from '~/vue_shared/directives/safe_html'; +import { SERVICE_PING_SECURITY_CONFIGURATION_THREAT_MANAGEMENT_VISIT } from '~/tracking/constants'; import AutoDevOpsAlert from './auto_dev_ops_alert.vue'; import AutoDevOpsEnabledAlert from './auto_dev_ops_enabled_alert.vue'; -import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY } from './constants'; +import { + AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY, + TAB_VULNERABILITY_MANAGEMENT_INDEX, +} from './constants'; import FeatureCard from './feature_card.vue'; import TrainingProviderList from './training_provider_list.vue'; @@ -123,6 +128,11 @@ export default { dismissAlert() { this.errorMessage = ''; }, + tabChange(value) { + if (value === TAB_VULNERABILITY_MANAGEMENT_INDEX) { + Api.trackRedisHllUserEvent(SERVICE_PING_SECURITY_CONFIGURATION_THREAT_MANAGEMENT_VISIT); + } + }, }, autoDevopsEnabledAlertStorageKey: AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY, }; @@ -167,6 +177,7 @@ export default { data-testid="security-configuration-container" sync-active-tab-with-query-params lazy + @input="tabChange" > <gl-tab data-testid="security-testing-tab" diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js index b427820144d..fd713a7a504 100644 --- a/app/assets/javascripts/security_configuration/components/constants.js +++ b/app/assets/javascripts/security_configuration/components/constants.js @@ -326,3 +326,5 @@ export const TEMP_PROVIDER_URLS = { [__('Secure Code Warrior')]: 'https://www.securecodewarrior.com/', SecureFlag: 'https://www.secureflag.com/', }; + +export const TAB_VULNERABILITY_MANAGEMENT_INDEX = 1; diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue index 930e7ff12d9..ef7f12f273f 100644 --- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue +++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue @@ -1,4 +1,5 @@ <script> +import { GlButton } from '@gitlab/ui'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/issues/constants'; import { __, sprintf } from '~/locale'; @@ -9,6 +10,7 @@ const DEFAULT_RENDER_COUNT = 5; export default { components: { + GlButton, AssigneeAvatarLink, UserNameWithStatus, }, @@ -97,10 +99,11 @@ export default { </assignee-avatar-link> </div> </div> - <div v-if="renderShowMoreSection" class="user-list-more gl-hover-text-blue-800"> - <button - type="button" - class="btn-link gl-button gl-reset-color!" + <div v-if="renderShowMoreSection" class="gl-hover-text-blue-800" data-testid="user-list-more"> + <gl-button + category="tertiary" + size="small" + data-testid="user-list-more-button" data-qa-selector="more_assignees_link" @click="toggleShowLess" > @@ -108,7 +111,7 @@ export default { {{ hiddenAssigneesLabel }} </template> <template v-else>{{ __('- show less') }}</template> - </button> + </gl-button> </div> </div> </template> diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue index 7b288e15a3e..99d36a61632 100644 --- a/app/assets/javascripts/sidebar/components/participants/participants.vue +++ b/app/assets/javascripts/sidebar/components/participants/participants.vue @@ -138,13 +138,10 @@ export default { </a> </div> </div> - <div v-if="hasMoreParticipants" class="participants-more hide-collapsed"> - <gl-button - variant="link" - button-text-classes="gl-text-secondary" - @click="toggleMoreParticipants" - >{{ toggleLabel }}</gl-button - > + <div v-if="hasMoreParticipants" class="hide-collapsed"> + <gl-button category="tertiary" size="small" @click="toggleMoreParticipants">{{ + toggleLabel + }}</gl-button> </div> </div> </template> diff --git a/app/assets/javascripts/tracking/constants.js b/app/assets/javascripts/tracking/constants.js index 114587bb363..7c4bff18272 100644 --- a/app/assets/javascripts/tracking/constants.js +++ b/app/assets/javascripts/tracking/constants.js @@ -31,3 +31,8 @@ export const GOOGLE_ANALYTICS_ID_COOKIE_NAME = '_ga'; export const GITLAB_INTERNAL_EVENT_CATEGORY = 'InternalEventTracking'; export const SERVICE_PING_SCHEMA = 'iglu:com.gitlab/gitlab_service_ping/jsonschema/1-0-0'; + +export const SERVICE_PING_SECURITY_CONFIGURATION_THREAT_MANAGEMENT_VISIT = + 'users_visiting_security_configuration_threat_management'; + +export const SERVICE_PING_PIPELINE_SECURITY_VISIT = 'users_visiting_pipeline_security'; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue index e94e0fbe6dc..eec51ddde53 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue @@ -205,9 +205,7 @@ export default { data-qa-selector="merge_request_pipeline_info_content" class="gl-display-flex gl-flex-wrap gl-align-items-center gl-justify-content-space-between" > - <p - class="mr-pipeline-title gl-m-0! gl-mr-3! gl-font-weight-bold gl-line-height-32 gl-text-gray-900" - > + <p class="mr-pipeline-title gl-m-0! gl-mr-3! gl-font-weight-bold gl-text-gray-900"> {{ pipeline.details.event_type_name }} <gl-link :href="pipeline.path" @@ -253,7 +251,7 @@ export default { v-safe-html="sourceBranchLink" :title="sourceBranch" truncate-target="child" - class="label-branch label-truncate gl-font-weight-normal gl-vertical-align-text-bottom" + class="label-branch label-truncate gl-font-weight-normal" /> </template> <template v-if="finishedAt"> diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index acdcbf7afd7..537fdf8cdf8 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -569,7 +569,7 @@ export default { v-if="hasMergeError" type="danger" dismissible - data-testid="merge_error" + data-testid="merge-error" > <span v-safe-html="mergeError"></span> </mr-widget-alert-message> @@ -577,6 +577,7 @@ export default { v-if="showMergePipelineForkWarning" type="warning" :help-path="mr.mergeRequestPipelinesHelpPath" + data-testid="merge-pipeline-fork-warning" > {{ s__( diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 5f90dd62426..600a40da98b 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -799,29 +799,6 @@ } } -.participants-more, -.user-list-more { - margin-left: 5px; - - a, - .btn-link { - color: $gl-text-color-secondary; - } - - .btn-link { - padding: 0; - } - - .btn-link:hover { - color: $blue-800; - text-decoration: none; - } - - .btn-link:focus { - text-decoration: none; - } -} - .sidebar-help-wrap { .sidebar-help-state { margin: 16px -20px -20px; diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss index c2c38de9aca..14c23c2b7a9 100644 --- a/app/assets/stylesheets/page_bundles/merge_requests.scss +++ b/app/assets/stylesheets/page_bundles/merge_requests.scss @@ -416,7 +416,7 @@ $tabs-holder-z-index: 250; .media-body { min-width: 0; - font-size: 12px; + font-size: $gl-font-size-sm; margin-left: 32px; } @@ -648,7 +648,6 @@ $tabs-holder-z-index: 250; .label-branch { @include gl-font-monospace; - font-size: 95%; overflow: hidden; word-break: break-all; } @@ -662,7 +661,7 @@ $tabs-holder-z-index: 250; > span { display: inline-block; max-width: 12.5em; - margin-bottom: -5px; + margin-bottom: px-to-rem(-5px); white-space: nowrap; text-overflow: ellipsis; overflow: hidden; diff --git a/app/channels/noteable/notes_channel.rb b/app/channels/noteable/notes_channel.rb index 021bc3ccd1b..8ce6c15e123 100644 --- a/app/channels/noteable/notes_channel.rb +++ b/app/channels/noteable/notes_channel.rb @@ -13,7 +13,6 @@ module Noteable }).target return reject if noteable.nil? - return reject if Feature.disabled?(:action_cable_notes, project || noteable.try(:group)) stream_for noteable rescue ActiveRecord::RecordNotFound diff --git a/app/controllers/concerns/preferred_language_switcher.rb b/app/controllers/concerns/preferred_language_switcher.rb index 872652100c9..5ac75e40b04 100644 --- a/app/controllers/concerns/preferred_language_switcher.rb +++ b/app/controllers/concerns/preferred_language_switcher.rb @@ -2,6 +2,8 @@ module PreferredLanguageSwitcher extend ActiveSupport::Concern + include Gitlab::Utils::StrongMemoize + include PreferredLanguageSwitcherHelper private @@ -11,8 +13,36 @@ module PreferredLanguageSwitcher def preferred_language cookies[:preferred_language].presence_in(Gitlab::I18n.available_locales) || + selectable_language(marketing_site_language) || + selectable_language(browser_languages) || Gitlab::CurrentSettings.default_preferred_language end + + def selectable_language(language_options) + language_options.find { |lan| ordered_selectable_locales_codes.include?(lan) } + end + + def browser_languages + http_language_header = request.env['HTTP_ACCEPT_LANGUAGE'] + return [] unless http_language_header + + http_language_header.tr!('-', '_').split(%r{[;,]}).reject { |str| str.start_with?('q') } + end + strong_memoize_attr :browser_languages + + def marketing_site_language + return [] unless params[:glm_source] + + locale = params[:glm_source].scan(%r{(\w{2})-(\w{2})/}).flatten + + return [] if locale.empty? + + [locale[0], "#{locale[0]}_#{locale[1]}"] + end + + def ordered_selectable_locales_codes + ordered_selectable_locales.map { |locale| locale[:value] } # rubocop:disable Rails/Pluck + end end PreferredLanguageSwitcher.prepend_mod diff --git a/app/controllers/projects/environments/sample_metrics_controller.rb b/app/controllers/projects/environments/sample_metrics_controller.rb deleted file mode 100644 index 80344c83ab7..00000000000 --- a/app/controllers/projects/environments/sample_metrics_controller.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -class Projects::Environments::SampleMetricsController < Projects::ApplicationController - feature_category :metrics - urgency :low - - def query - result = Metrics::SampleMetricsService.new(params[:identifier], range_start: params[:start], range_end: params[:end]).query - - if result - render json: { "status": "success", "data": { "resultType": "matrix", "result": result } } - else - render_404 - end - end -end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 99055d5c6b7..620f900a751 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -73,7 +73,6 @@ class Projects::IssuesController < Projects::ApplicationController push_frontend_feature_flag(:epic_widget_edit_confirmation, project) push_frontend_feature_flag(:moved_mr_sidebar, project) push_frontend_feature_flag(:move_close_into_dropdown, project) - push_frontend_feature_flag(:action_cable_notes, project) end around_action :allow_gitaly_ref_name_caching, only: [:discussions] diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index cfa7117b272..f5a9e9e6fd3 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -49,7 +49,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo push_frontend_feature_flag(:mr_activity_filters, current_user) push_frontend_feature_flag(:review_apps_redeploy_mr_widget, project) push_frontend_feature_flag(:ci_job_failures_in_mr, project) - push_frontend_feature_flag(:action_cable_notes, project) push_frontend_feature_flag(:mr_pipelines_graphql, project) end diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb index 639db58b00d..0336135835a 100644 --- a/app/finders/group_members_finder.rb +++ b/app/finders/group_members_finder.rb @@ -20,6 +20,8 @@ class GroupMembersFinder < UnionFinder # search: string # created_after: datetime # created_before: datetime + # non_invite: boolean + # with_custom_role: boolean attr_reader :params def initialize(group, user = nil, params: {}) @@ -34,7 +36,10 @@ class GroupMembersFinder < UnionFinder Group.shared_into_ancestors(group).public_or_visible_to_user(user) end - members = all_group_members(groups, shared_from_groups).distinct_on_user_with_max_access_level + members = all_group_members(groups, shared_from_groups) + if static_roles_only? + members = members.distinct_on_user_with_max_access_level + end filter_members(members) end @@ -70,7 +75,10 @@ class GroupMembersFinder < UnionFinder members = filter_by_user_type(members) members = apply_additional_filters(members) - by_created_at(members) + members = by_created_at(members) + members = members.non_invite if params[:non_invite] + + members end def can_manage_members @@ -137,6 +145,10 @@ class GroupMembersFinder < UnionFinder # overridden in EE to include additional filtering conditions. members end + + def static_roles_only? + true + end end GroupMembersFinder.prepend_mod_with('GroupMembersFinder') diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb index 40a91c8ac94..411c343a7d7 100644 --- a/app/models/concerns/noteable.rb +++ b/app/models/concerns/noteable.rb @@ -175,7 +175,7 @@ module Noteable # TODO: We need to figure out a way to make ETag caching work for group-level work items Gitlab::EtagCaching::Store.new.touch(note_etag_key) unless is_a?(Issue) && project.nil? - Noteable::NotesChannel.broadcast_to(self, event: 'updated') if Feature.enabled?(:action_cable_notes, project || try(:group)) + Noteable::NotesChannel.broadcast_to(self, event: 'updated') end def note_etag_key diff --git a/app/models/metrics/users_starred_dashboard.rb b/app/models/metrics/users_starred_dashboard.rb deleted file mode 100644 index 07748eb1431..00000000000 --- a/app/models/metrics/users_starred_dashboard.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module Metrics - class UsersStarredDashboard < ApplicationRecord - self.table_name = 'metrics_users_starred_dashboards' - - belongs_to :user, inverse_of: :metrics_users_starred_dashboards - belongs_to :project, inverse_of: :metrics_users_starred_dashboards - - validates :user_id, presence: true - validates :project_id, presence: true - validates :dashboard_path, presence: true, length: { maximum: 255 } - validates :dashboard_path, uniqueness: { scope: %i[user_id project_id] } - - scope :for_project, ->(project) { where(project: project) } - scope :for_project_dashboard, ->(project, path) { for_project(project).where(dashboard_path: path) } - end -end diff --git a/app/models/project.rb b/app/models/project.rb index a57a3247c8a..3d97628c216 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -373,7 +373,6 @@ class Project < ApplicationRecord has_many :prometheus_alerts, inverse_of: :project has_many :prometheus_alert_events, inverse_of: :project has_many :self_managed_prometheus_alert_events, inverse_of: :project - has_many :metrics_users_starred_dashboards, class_name: 'Metrics::UsersStarredDashboard', inverse_of: :project has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :project has_many :alert_management_http_integrations, class_name: 'AlertManagement::HttpIntegration', inverse_of: :project diff --git a/app/models/user.rb b/app/models/user.rb index 343034b1e38..2d679a6b614 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -258,8 +258,6 @@ class User < MainClusterwide::ApplicationRecord has_many :organization_users, class_name: 'Organizations::OrganizationUser', inverse_of: :user has_many :organizations, through: :organization_users, class_name: 'Organizations::Organization', inverse_of: :users - has_many :metrics_users_starred_dashboards, class_name: 'Metrics::UsersStarredDashboard', inverse_of: :user - has_one :status, class_name: 'UserStatus' has_one :user_preference has_one :user_detail diff --git a/app/services/compare_service.rb b/app/services/compare_service.rb index 569b91de73e..b02cfea151d 100644 --- a/app/services/compare_service.rb +++ b/app/services/compare_service.rb @@ -17,9 +17,6 @@ class CompareService return unless raw_compare && raw_compare.base && raw_compare.head - Compare.new(raw_compare, - start_project, - base_sha: base_sha, - straight: straight) + Compare.new(raw_compare, start_project, base_sha: base_sha, straight: straight) end end diff --git a/app/services/concerns/rate_limited_service.rb b/app/services/concerns/rate_limited_service.rb index fa366c1ccd0..79be952ac14 100644 --- a/app/services/concerns/rate_limited_service.rb +++ b/app/services/concerns/rate_limited_service.rb @@ -61,9 +61,11 @@ module RateLimitedService cattr_accessor :rate_limiter_scoped_and_keyed def self.rate_limit(key:, opts:, rate_limiter: ::Gitlab::ApplicationRateLimiter) - self.rate_limiter_scoped_and_keyed = RateLimiterScopedAndKeyed.new(key: key, - opts: opts, - rate_limiter: rate_limiter) + self.rate_limiter_scoped_and_keyed = RateLimiterScopedAndKeyed.new( + key: key, + opts: opts, + rate_limiter: rate_limiter + ) end end diff --git a/app/services/design_management/copy_design_collection/copy_service.rb b/app/services/design_management/copy_design_collection/copy_service.rb index 8074a193bbf..d391c13696f 100644 --- a/app/services/design_management/copy_design_collection/copy_service.rb +++ b/app/services/design_management/copy_design_collection/copy_service.rb @@ -58,8 +58,8 @@ module DesignManagement private attr_reader :designs, :event_enum_map, :git_user, :sha_attribute, :shas, - :temporary_branch, :target_design_collection, :target_issue, - :target_repository, :target_project, :versions + :temporary_branch, :target_design_collection, :target_issue, + :target_repository, :target_project, :versions alias_method :merge_branch, :target_branch diff --git a/app/services/design_management/delete_designs_service.rb b/app/services/design_management/delete_designs_service.rb index 921c904d8de..a6a0f5e0252 100644 --- a/app/services/design_management/delete_designs_service.rb +++ b/app/services/design_management/delete_designs_service.rb @@ -16,8 +16,10 @@ module DesignManagement version = delete_designs! EventCreateService.new.destroy_designs(designs, current_user) - Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_designs_removed_action(author: current_user, - project: project) + Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_designs_removed_action( + author: current_user, + project: project + ) TodosDestroyer::DestroyedDesignsWorker.perform_async(designs.map(&:id)) success(version: version) diff --git a/app/services/design_management/runs_design_actions.rb b/app/services/design_management/runs_design_actions.rb index 267ed6bf29f..62db7824592 100644 --- a/app/services/design_management/runs_design_actions.rb +++ b/app/services/design_management/runs_design_actions.rb @@ -15,10 +15,12 @@ module DesignManagement def run_actions(actions, skip_system_notes: false) raise NoActions if actions.empty? - sha = repository.commit_files(current_user, - branch_name: target_branch, - message: commit_message, - actions: actions.map(&:gitaly_action)) + sha = repository.commit_files( + current_user, + branch_name: target_branch, + message: commit_message, + actions: actions.map(&:gitaly_action) + ) ::DesignManagement::Version .create_for_designs(actions, sha, current_user) diff --git a/app/services/design_management/save_designs_service.rb b/app/services/design_management/save_designs_service.rb index ea5675c6ddd..4c4e34862e8 100644 --- a/app/services/design_management/save_designs_service.rb +++ b/app/services/design_management/save_designs_service.rb @@ -131,11 +131,11 @@ module DesignManagement def track_usage_metrics(action) if action == :update - ::Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_designs_modified_action(author: current_user, - project: project) + ::Gitlab::UsageDataCounters::IssueActivityUniqueCounter + .track_issue_designs_modified_action(author: current_user, project: project) else - ::Gitlab::UsageDataCounters::IssueActivityUniqueCounter.track_issue_designs_added_action(author: current_user, - project: project) + ::Gitlab::UsageDataCounters::IssueActivityUniqueCounter + .track_issue_designs_added_action(author: current_user, project: project) end ::Gitlab::UsageDataCounters::DesignsCounter.count(action) diff --git a/app/services/error_tracking/base_service.rb b/app/services/error_tracking/base_service.rb index 8458eb1f3b8..e95d4eec3c8 100644 --- a/app/services/error_tracking/base_service.rb +++ b/app/services/error_tracking/base_service.rb @@ -17,8 +17,7 @@ module ErrorTracking private def perform - raise NotImplementedError, - "#{self.class} does not implement #{__method__}" + raise NotImplementedError, "#{self.class} does not implement #{__method__}" end def compose_response(response, &block) @@ -33,8 +32,7 @@ module ErrorTracking end def parse_response(response) - raise NotImplementedError, - "#{self.class} does not implement #{__method__}" + raise NotImplementedError, "#{self.class} does not implement #{__method__}" end def unauthorized diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb index 1893cfcfcff..b755f512772 100644 --- a/app/services/event_create_service.rb +++ b/app/services/event_create_service.rb @@ -190,10 +190,14 @@ class EventCreateService private def create_record_event(record, current_user, status, fingerprint = nil) - create_event(record.resource_parent, current_user, status, - fingerprint: fingerprint, - target_id: record.id, - target_type: record.class.name) + create_event( + record.resource_parent, + current_user, + status, + fingerprint: fingerprint, + target_id: record.id, + target_type: record.class.name + ) end # If creating several events, this method will insert them all in a single diff --git a/app/services/files/update_service.rb b/app/services/files/update_service.rb index 9fa966bb8a8..c11917b92ec 100644 --- a/app/services/files/update_service.rb +++ b/app/services/files/update_service.rb @@ -3,15 +3,19 @@ module Files class UpdateService < Files::BaseService def create_commit! - repository.update_file(current_user, @file_path, @file_content, - message: @commit_message, - branch_name: @branch_name, - previous_path: @previous_path, - author_email: @author_email, - author_name: @author_name, - start_project: @start_project, - start_branch_name: @start_branch, - execute_filemode: @execute_filemode) + repository.update_file( + current_user, + @file_path, + @file_content, + message: @commit_message, + branch_name: @branch_name, + previous_path: @previous_path, + author_email: @author_email, + author_name: @author_name, + start_project: @start_project, + start_branch_name: @start_branch, + execute_filemode: @execute_filemode + ) end private diff --git a/app/services/google_cloud/create_cloudsql_instance_service.rb b/app/services/google_cloud/create_cloudsql_instance_service.rb index 8d040c6c908..9a1263f0796 100644 --- a/app/services/google_cloud/create_cloudsql_instance_service.rb +++ b/app/services/google_cloud/create_cloudsql_instance_service.rb @@ -17,26 +17,30 @@ module GoogleCloud private def create_cloud_instance - google_api_client.create_cloudsql_instance(gcp_project_id, - instance_name, - root_password, - database_version, - region, - tier) + google_api_client.create_cloudsql_instance( + gcp_project_id, + instance_name, + root_password, + database_version, + region, + tier + ) end def trigger_instance_setup_worker - GoogleCloud::CreateCloudsqlInstanceWorker.perform_in(WORKER_INTERVAL, - current_user.id, - project.id, - { - 'google_oauth2_token': google_oauth2_token, - 'gcp_project_id': gcp_project_id, - 'instance_name': instance_name, - 'database_version': database_version, - 'environment_name': environment_name, - 'is_protected': protected? - }) + GoogleCloud::CreateCloudsqlInstanceWorker.perform_in( + WORKER_INTERVAL, + current_user.id, + project.id, + { + 'google_oauth2_token': google_oauth2_token, + 'gcp_project_id': gcp_project_id, + 'instance_name': instance_name, + 'database_version': database_version, + 'environment_name': environment_name, + 'is_protected': protected? + } + ) end def protected? diff --git a/app/services/google_cloud/fetch_google_ip_list_service.rb b/app/services/google_cloud/fetch_google_ip_list_service.rb index f7739971603..54af841d002 100644 --- a/app/services/google_cloud/fetch_google_ip_list_service.rb +++ b/app/services/google_cloud/fetch_google_ip_list_service.rb @@ -18,9 +18,11 @@ module GoogleCloud subnets = fetch_and_update_cache! - Gitlab::AppJsonLogger.info(class: self.class.name, - message: 'Successfully retrieved Google IP list', - subnet_count: subnets.count) + Gitlab::AppJsonLogger.info( + class: self.class.name, + message: 'Successfully retrieved Google IP list', + subnet_count: subnets.count + ) success({ subnets: subnets }) rescue IpListNotRetrievedError => err diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb index 6c229dca58c..f546bd5951a 100644 --- a/app/services/issuable_base_service.rb +++ b/app/services/issuable_base_service.rb @@ -184,11 +184,14 @@ class IssuableBaseService < ::BaseContainerService end def process_assignee_ids(attributes, existing_assignee_ids: nil, extra_assignee_ids: []) - process = Issuable::ProcessAssignees.new(assignee_ids: attributes.delete(:assignee_ids), - add_assignee_ids: attributes.delete(:add_assignee_ids), - remove_assignee_ids: attributes.delete(:remove_assignee_ids), - existing_assignee_ids: existing_assignee_ids, - extra_assignee_ids: extra_assignee_ids) + process = Issuable::ProcessAssignees.new( + assignee_ids: attributes.delete(:assignee_ids), + add_assignee_ids: attributes.delete(:add_assignee_ids), + remove_assignee_ids: attributes.delete(:remove_assignee_ids), + existing_assignee_ids: existing_assignee_ids, + extra_assignee_ids: extra_assignee_ids + ) + process.execute end @@ -373,9 +376,11 @@ class IssuableBaseService < ::BaseContainerService filter_params(issuable) if issuable.changed? || params.present? - issuable.assign_attributes(params.merge(updated_by: current_user, - last_edited_at: Time.current, - last_edited_by: current_user)) + issuable.assign_attributes(params.merge( + updated_by: current_user, + last_edited_at: Time.current, + last_edited_by: current_user + )) before_update(issuable, skip_spam_check: true) @@ -404,10 +409,13 @@ class IssuableBaseService < ::BaseContainerService update_task_params = params.delete(:update_task) return unless update_task_params - tasklist_toggler = TaskListToggleService.new(issuable.description, issuable.description_html, - line_source: update_task_params[:line_source], - line_number: update_task_params[:line_number].to_i, - toggle_as_checked: update_task_params[:checked]) + tasklist_toggler = TaskListToggleService.new( + issuable.description, + issuable.description_html, + line_source: update_task_params[:line_source], + line_number: update_task_params[:line_number].to_i, + toggle_as_checked: update_task_params[:checked] + ) unless tasklist_toggler.execute # if we make it here, the data is much newer than we thought it was - fail fast diff --git a/app/services/issues/close_service.rb b/app/services/issues/close_service.rb index 28f4c6d5904..ef43e707a21 100644 --- a/app/services/issues/close_service.rb +++ b/app/services/issues/close_service.rb @@ -6,10 +6,12 @@ module Issues def execute(issue, commit: nil, notifications: true, system_note: true, skip_authorization: false) return issue unless can_close?(issue, skip_authorization: skip_authorization) - close_issue(issue, - closed_via: commit, - notifications: notifications, - system_note: system_note) + close_issue( + issue, + closed_via: commit, + notifications: notifications, + system_note: system_note + ) end # Closes the supplied issue without checking if the user is authorized to diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb index e1ddfe47439..c828c156d50 100644 --- a/app/services/issues/create_service.rb +++ b/app/services/issues/create_service.rb @@ -7,7 +7,7 @@ module Issues include ::Services::ReturnServiceResponses rate_limit key: :issues_create, - opts: { scope: [:project, :current_user, :external_author] } + opts: { scope: [:project, :current_user, :external_author] } def initialize(container:, current_user: nil, params: {}, build_service: nil, perform_spam_check: true) @extra_params = params.delete(:extra_params) || {} @@ -90,9 +90,12 @@ module Issues def resolve_discussions_with_issue(issue) return if discussions_to_resolve.empty? - Discussions::ResolveService.new(project, current_user, - one_or_more_discussions: discussions_to_resolve, - follow_up_issue: issue).execute + Discussions::ResolveService.new( + project, + current_user, + one_or_more_discussions: discussions_to_resolve, + follow_up_issue: issue + ).execute end private diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb index e26e3d0835b..c3ddf7b6709 100644 --- a/app/services/issues/move_service.rb +++ b/app/services/issues/move_service.rb @@ -141,15 +141,23 @@ module Issues end def add_note_from - SystemNoteService.noteable_moved(new_entity, target_project, - original_entity, current_user, - direction: :from) + SystemNoteService.noteable_moved( + new_entity, + target_project, + original_entity, + current_user, + direction: :from + ) end def add_note_to - SystemNoteService.noteable_moved(original_entity, old_project, - new_entity, current_user, - direction: :to) + SystemNoteService.noteable_moved( + original_entity, + old_project, + new_entity, + current_user, + direction: :to + ) end end end diff --git a/app/services/metrics/sample_metrics_service.rb b/app/services/metrics/sample_metrics_service.rb deleted file mode 100644 index 9bf32b295e2..00000000000 --- a/app/services/metrics/sample_metrics_service.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -module Metrics - class SampleMetricsService - DIRECTORY = "sample_metrics" - - attr_reader :identifier, :range_minutes - - def initialize(identifier, range_start:, range_end:) - @identifier = identifier - @range_minutes = convert_range_minutes(range_start, range_end) - end - - def query - return unless identifier && File.exist?(file_location) - - query_interval - end - - private - - def file_location - sanitized_string = identifier.gsub(/[^0-9A-Za-z_]/, '') - File.join(Rails.root, DIRECTORY, "#{sanitized_string}.yml") - end - - def query_interval - result = YAML.load_file(File.expand_path(file_location, __dir__)) - result[range_minutes] - end - - def convert_range_minutes(range_start, range_end) - ((range_end.to_time - range_start.to_time) / 1.minute).to_i - end - end -end diff --git a/app/views/groups/dependency_proxies/show.html.haml b/app/views/groups/dependency_proxies/show.html.haml index 8416cb81c95..02a024ed3b5 100644 --- a/app/views/groups/dependency_proxies/show.html.haml +++ b/app/views/groups/dependency_proxies/show.html.haml @@ -1,6 +1,7 @@ - page_title _("Dependency Proxy") #js-dependency-proxy{ data: { group_path: @group.full_path, + endpoint: group_dependency_proxy_path(@group), no_manifests_illustration: image_path('illustrations/docker-empty-state.svg'), group_id: @group.id, settings_path: group_settings_packages_and_registries_path(@group), diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml index 681d4e087f3..51010ec326e 100644 --- a/app/views/profiles/preferences/show.html.haml +++ b/app/views/profiles/preferences/show.html.haml @@ -140,7 +140,7 @@ %p.gl-text-secondary = s_('Preferences|Configure how dates and times display for you.') = succeed '.' do - = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'time-preferences'), target: '_blank', rel: 'noopener noreferrer' + = link_to _('Learn more'), help_page_path('user/profile/preferences', anchor: 'show-exact-times-instead-of-relative-times'), target: '_blank', rel: 'noopener noreferrer' .form-group = f.gitlab_ui_checkbox_component :time_display_relative, s_('Preferences|Use relative times'), |