diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-10 21:09:54 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-10 21:09:54 +0300 |
commit | 350fd8b878fe930b83c52ccae82f861cc499776a (patch) | |
tree | aa01a35b06921103ba9967920165419accb9f72d | |
parent | 70732753863e569f95ed954ca3c41421292f912b (diff) |
Add latest changes from gitlab-org/gitlab@master
162 files changed, 843 insertions, 337 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 903dc5fdcd0..7f77f69c267 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1325,14 +1325,6 @@ Rails/SaveBang: - 'spec/features/issues/user_filters_issues_spec.rb' - 'spec/features/issues/user_sees_live_update_spec.rb' - 'spec/features/issues/user_sorts_issues_spec.rb' - - 'spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb' - - 'spec/features/merge_request/user_posts_diff_notes_spec.rb' - - 'spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb' - - 'spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb' - - 'spec/features/merge_request/user_sees_discussions_spec.rb' - - 'spec/features/merge_request/user_sees_merge_widget_spec.rb' - - 'spec/features/merge_request/user_sees_versions_spec.rb' - - 'spec/features/merge_requests/user_mass_updates_spec.rb' - 'spec/features/profiles/emails_spec.rb' - 'spec/features/profiles/password_spec.rb' - 'spec/features/profiles/personal_access_tokens_spec.rb' diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue index 92203381154..8fb383a5d73 100644 --- a/app/assets/javascripts/batch_comments/components/draft_note.vue +++ b/app/assets/javascripts/batch_comments/components/draft_note.vue @@ -1,7 +1,7 @@ <script> import { mapActions, mapGetters, mapState } from 'vuex'; import NoteableNote from '~/notes/components/noteable_note.vue'; -import LoadingButton from '~/vue_shared/components/loading_button.vue'; +import { GlButton } from '@gitlab/ui'; import PublishButton from './publish_button.vue'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; @@ -9,7 +9,7 @@ export default { components: { NoteableNote, PublishButton, - LoadingButton, + GlButton, }, mixins: [glFeatureFlagsMixin()], props: { @@ -115,18 +115,15 @@ export default { ></div> <p class="draft-note-actions d-flex"> - <publish-button - :show-count="true" - :should-publish="false" - class="btn btn-success btn-inverted gl-mr-3" - /> - <loading-button + <publish-button :show-count="true" :should-publish="false" category="secondary" /> + <gl-button ref="publishNowButton" :loading="isPublishingDraft(draft.id) || isPublishing" - :label="__('Add comment now')" - container-class="btn btn-inverted" + class="gl-ml-3" @click="publishNow" - /> + > + {{ __('Add comment now') }} + </gl-button> </p> </template> </article> diff --git a/app/assets/javascripts/batch_comments/components/drafts_count.vue b/app/assets/javascripts/batch_comments/components/drafts_count.vue index f1180760c4d..7a8482ac341 100644 --- a/app/assets/javascripts/batch_comments/components/drafts_count.vue +++ b/app/assets/javascripts/batch_comments/components/drafts_count.vue @@ -1,15 +1,19 @@ <script> import { mapGetters } from 'vuex'; +import { GlBadge } from '@gitlab/ui'; export default { + components: { + GlBadge, + }, computed: { ...mapGetters('batchComments', ['draftsCount']), }, }; </script> <template> - <span class="drafts-count-component"> - <span class="drafts-count-number">{{ draftsCount }}</span> + <gl-badge size="sm" variant="success"> + {{ draftsCount }} <span class="sr-only"> {{ n__('draft', 'drafts', draftsCount) }} </span> - </span> + </gl-badge> </template> diff --git a/app/assets/javascripts/batch_comments/components/publish_button.vue b/app/assets/javascripts/batch_comments/components/publish_button.vue index f4dc0f04dc3..33d4ff6b19a 100644 --- a/app/assets/javascripts/batch_comments/components/publish_button.vue +++ b/app/assets/javascripts/batch_comments/components/publish_button.vue @@ -1,12 +1,12 @@ <script> import { mapActions, mapState } from 'vuex'; import { __ } from '~/locale'; -import LoadingButton from '~/vue_shared/components/loading_button.vue'; +import { GlButton } from '@gitlab/ui'; import DraftsCount from './drafts_count.vue'; export default { components: { - LoadingButton, + GlButton, DraftsCount, }, props: { @@ -20,6 +20,16 @@ export default { required: false, default: __('Finish review'), }, + category: { + type: String, + required: false, + default: 'primary', + }, + variant: { + type: String, + required: false, + default: 'success', + }, shouldPublish: { type: Boolean, required: true, @@ -42,14 +52,14 @@ export default { </script> <template> - <loading-button + <gl-button :loading="isPublishing" - container-class="btn btn-success js-publish-draft-button qa-submit-review" + class="js-publish-draft-button qa-submit-review" + :category="category" + :variant="variant" @click="onClick" > - <span> - {{ label }} - <drafts-count v-if="showCount" /> - </span> - </loading-button> + {{ label }} + <drafts-count v-if="showCount" /> + </gl-button> </template> diff --git a/app/assets/javascripts/environments/components/environment_external_url.vue b/app/assets/javascripts/environments/components/environment_external_url.vue index af537cfb991..793f7bf0681 100644 --- a/app/assets/javascripts/environments/components/environment_external_url.vue +++ b/app/assets/javascripts/environments/components/environment_external_url.vue @@ -1,6 +1,5 @@ <script> -import { GlTooltipDirective } from '@gitlab/ui'; -import Icon from '~/vue_shared/components/icon.vue'; +import { GlTooltipDirective, GlButton } from '@gitlab/ui'; import { s__ } from '~/locale'; /** @@ -8,7 +7,7 @@ import { s__ } from '~/locale'; */ export default { components: { - Icon, + GlButton, }, directives: { GlTooltip: GlTooltipDirective, @@ -27,15 +26,14 @@ export default { }; </script> <template> - <a + <gl-button v-gl-tooltip :title="title" :aria-label="title" :href="externalUrl" - class="btn external-url" + class="external-url" target="_blank" + icon="external-link" rel="noopener noreferrer nofollow" - > - <icon name="external-link" /> - </a> + /> </template> diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue index 99f50b499d0..c63d54d586d 100644 --- a/app/assets/javascripts/environments/components/environment_stop.vue +++ b/app/assets/javascripts/environments/components/environment_stop.vue @@ -5,16 +5,13 @@ */ import $ from 'jquery'; -import { GlTooltipDirective } from '@gitlab/ui'; -import Icon from '~/vue_shared/components/icon.vue'; +import { GlTooltipDirective, GlButton } from '@gitlab/ui'; import { s__ } from '~/locale'; import eventHub from '../event_hub'; -import LoadingButton from '../../vue_shared/components/loading_button.vue'; export default { components: { - Icon, - LoadingButton, + GlButton, }, directives: { GlTooltip: GlTooltipDirective, @@ -55,16 +52,16 @@ export default { }; </script> <template> - <loading-button + <gl-button v-gl-tooltip :loading="isLoading" :title="title" :aria-label="title" - container-class="btn btn-danger d-none d-sm-none d-md-block" + icon="stop" + category="primary" + variant="danger" data-toggle="modal" data-target="#stop-environment-modal" @click="onClick" - > - <icon name="stop" /> - </loading-button> + /> </template> diff --git a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue index e2909333d74..0c4abc14494 100644 --- a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue +++ b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue @@ -20,8 +20,18 @@ export default { }, }, computed: { + /** + * Both Epic and Roadmap pages share same recents store + * and with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36421 + * Roadmap started using `GlFilteredSearch` which is not compatible + * with string tokens stored in recents, so this is a temporary + * fix by ignoring non-string recents while in Epic page. + */ + compatibleItems() { + return this.items.filter(item => typeof item === 'string'); + }, processedItems() { - return this.items.map(item => { + return this.compatibleItems.map(item => { const { tokens, searchToken } = FilteredSearchTokenizer.processTokens( item, this.allowedKeys, @@ -41,7 +51,7 @@ export default { }); }, hasItems() { - return this.items.length > 0; + return this.compatibleItems.length > 0; }, }, methods: { @@ -84,9 +94,7 @@ export default { <span class="value">{{ token.suffix }}</span> </span> </span> - <span class="filtered-search-history-dropdown-search-token"> - {{ item.searchToken }} - </span> + <span class="filtered-search-history-dropdown-search-token">{{ item.searchToken }}</span> </button> </li> <li class="divider"></li> diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue index c0e5196eb7b..a6503a18702 100644 --- a/app/assets/javascripts/incidents/components/incidents_list.vue +++ b/app/assets/javascripts/incidents/components/incidents_list.vue @@ -287,7 +287,7 @@ export default { <gl-icon v-if="item.state === 'closed'" name="issue-close" - class="gl-mx-1 gl-fill-blue-500" + class="gl-mx-1 gl-fill-blue-500 gl-flex-shrink-0" :size="16" data-testid="incident-closed" /> diff --git a/app/assets/javascripts/maintenance_mode_settings/components/app.vue b/app/assets/javascripts/maintenance_mode_settings/components/app.vue index 7798c443914..11d154ed9d1 100644 --- a/app/assets/javascripts/maintenance_mode_settings/components/app.vue +++ b/app/assets/javascripts/maintenance_mode_settings/components/app.vue @@ -1,5 +1,5 @@ <script> -import { GlToggle, GlFormGroup, GlFormTextarea, GlDeprecatedButton } from '@gitlab/ui'; +import { GlToggle, GlFormGroup, GlFormTextarea, GlButton } from '@gitlab/ui'; export default { name: 'MaintenanceModeSettingsApp', @@ -7,7 +7,7 @@ export default { GlToggle, GlFormGroup, GlFormTextarea, - GlDeprecatedButton, + GlButton, }, data() { return { @@ -38,7 +38,7 @@ export default { /> </gl-form-group> <div class="mt-4"> - <gl-deprecated-button variant="success">{{ __('Save changes') }}</gl-deprecated-button> + <gl-button variant="success" category="primary">{{ __('Save changes') }}</gl-button> </div> </article> </template> diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue index dff642161db..c7b72be36ad 100644 --- a/app/assets/javascripts/pipelines/components/header_component.vue +++ b/app/assets/javascripts/pipelines/components/header_component.vue @@ -1,7 +1,6 @@ <script> -import { GlLoadingIcon, GlModal, GlModalDirective } from '@gitlab/ui'; +import { GlLoadingIcon, GlModal, GlModalDirective, GlButton } from '@gitlab/ui'; import ciHeader from '~/vue_shared/components/header_ci_component.vue'; -import LoadingButton from '~/vue_shared/components/loading_button.vue'; import eventHub from '../event_hub'; import { __ } from '~/locale'; @@ -13,7 +12,7 @@ export default { ciHeader, GlLoadingIcon, GlModal, - LoadingButton, + GlButton, }, directives: { GlModal: GlModalDirective, @@ -77,35 +76,43 @@ export default { :user="pipeline.user" item-name="Pipeline" > - <loading-button + <gl-button v-if="pipeline.retry_path" :loading="isRetrying" :disabled="isRetrying" - class="js-retry-button btn btn-inverted-secondary" - container-class="d-inline" - :label="__('Retry')" + data-testid="retryButton" + category="secondary" + variant="info" @click="retryPipeline()" - /> + > + {{ __('Retry') }} + </gl-button> - <loading-button + <gl-button v-if="pipeline.cancel_path" :loading="isCanceling" :disabled="isCanceling" - class="js-btn-cancel-pipeline btn btn-danger" - container-class="d-inline" - :label="__('Cancel running')" + data-testid="cancelPipeline" + class="gl-ml-3" + category="primary" + variant="danger" @click="cancelPipeline()" - /> + > + {{ __('Cancel running') }} + </gl-button> - <loading-button + <gl-button v-if="pipeline.delete_path" v-gl-modal="$options.DELETE_MODAL_ID" :loading="isDeleting" :disabled="isDeleting" - class="js-btn-delete-pipeline btn btn-danger btn-inverted" - container-class="d-inline" - :label="__('Delete')" - /> + data-testid="deletePipeline" + class="gl-ml-3" + category="secondary" + variant="danger" + > + {{ __('Delete') }} + </gl-button> </ci-header> <gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-3 gl-mb-3" /> diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue index 2905b2ca26f..f0614298bd3 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue @@ -1,27 +1,15 @@ <script> -import { GlLink, GlTooltipDirective } from '@gitlab/ui'; -import { escape } from 'lodash'; +import { GlLink, GlPopover, GlSprintf, GlTooltipDirective } from '@gitlab/ui'; import { SCHEDULE_ORIGIN } from '../../constants'; -import { __, sprintf } from '~/locale'; -import popover from '~/vue_shared/directives/popover'; - -const popoverTitle = sprintf( - escape( - __( - `This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}`, - ), - ), - { strongStart: '<b>', strongEnd: '</b>' }, - false, -); export default { components: { GlLink, + GlPopover, + GlSprintf, }, directives: { GlTooltip: GlTooltipDirective, - popover, }, props: { pipeline: { @@ -44,23 +32,6 @@ export default { isScheduled() { return this.pipeline.source === SCHEDULE_ORIGIN; }, - popoverOptions() { - return { - html: true, - trigger: 'focus', - placement: 'top', - title: `<div class="autodevops-title"> - ${popoverTitle} - </div>`, - content: `<a - class="autodevops-link" - href="${this.autoDevopsHelpPath}" - target="_blank" - rel="noopener noreferrer nofollow"> - ${escape(__('Learn more about Auto DevOps'))} - </a>`, - }; - }, }, }; </script> @@ -114,13 +85,42 @@ export default { </span> <gl-link v-if="pipeline.flags.auto_devops" - v-popover="popoverOptions" + :id="`pipeline-url-autodevops-${pipeline.id}`" tabindex="0" class="js-pipeline-url-autodevops badge badge-info autodevops-badge" data-testid="pipeline-url-autodevops" role="button" >{{ __('Auto DevOps') }}</gl-link > + <gl-popover + :target="`pipeline-url-autodevops-${pipeline.id}`" + triggers="focus" + placement="top" + > + <template #title> + <div class="autodevops-title"> + <gl-sprintf + :message=" + __( + 'This pipeline makes use of a predefined CI/CD configuration enabled by %{strongStart}Auto DevOps.%{strongEnd}', + ) + " + > + <template #strong="{content}"> + <b>{{ content }}</b> + </template> + </gl-sprintf> + </div> + </template> + <gl-link + class="autodevops-link" + :href="autoDevopsHelpPath" + target="_blank" + rel="noopener noreferrer nofollow" + > + {{ __('Learn more about Auto DevOps') }} + </gl-link> + </gl-popover> <span v-if="pipeline.flags.stuck" class="js-pipeline-url-stuck badge badge-warning" diff --git a/app/assets/javascripts/releases/util.js b/app/assets/javascripts/releases/util.js index efb50dac9cf..842a423b142 100644 --- a/app/assets/javascripts/releases/util.js +++ b/app/assets/javascripts/releases/util.js @@ -10,13 +10,15 @@ import { * @param {string} createFrom The ref to create a new tag from, if necessary */ export const releaseToApiJson = (release, createFrom = null) => { + const name = release.name?.trim().length > 0 ? release.name.trim() : null; + const milestones = release.milestones ? release.milestones.map(milestone => milestone.title) : []; return convertObjectPropsToSnakeCase( { + name, tagName: release.tagName, ref: createFrom, - name: release.name, description: release.description, milestones, assets: release.assets, diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue index 5f0c115f70b..74f312d9b8f 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue @@ -44,7 +44,8 @@ export default { }, sortOptions: { type: Array, - required: true, + default: () => [], + required: false, }, initialFilterValue: { type: Array, @@ -63,7 +64,7 @@ export default { }, }, data() { - let selectedSortOption = this.sortOptions[0].sortDirection.descending; + let selectedSortOption = this.sortOptions[0]?.sortDirection?.descending; let selectedSortDirection = SortDirection.descending; // Extract correct sortBy value based on initialSortBy @@ -83,7 +84,7 @@ export default { return { initialRender: true, recentSearchesPromise: null, - recentSearches: null, + recentSearches: [], filterValue: this.initialFilterValue, selectedSortOption, selectedSortDirection, @@ -118,6 +119,9 @@ export default { ? __('Sort direction: Ascending') : __('Sort direction: Descending'); }, + filteredRecentSearches() { + return this.recentSearches.filter(item => typeof item !== 'string'); + }, }, watch: { /** @@ -246,7 +250,7 @@ export default { v-model="filterValue" :placeholder="searchInputPlaceholder" :available-tokens="tokens" - :history-items="recentSearches" + :history-items="filteredRecentSearches" class="flex-grow-1" @history-item-selected="handleHistoryItemSelected" @clear-history="handleClearHistory" @@ -264,7 +268,7 @@ export default { </template> </template> </gl-filtered-search> - <gl-button-group class="sort-dropdown-container d-flex"> + <gl-button-group v-if="selectedSortOption" class="sort-dropdown-container d-flex"> <gl-dropdown :text="selectedSortOption.title" :right="true" class="w-100"> <gl-dropdown-item v-for="sortBy in sortOptions" diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue index a40526794f3..0d9bc70d38f 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue @@ -3,7 +3,7 @@ import { GlToken, GlFilteredSearchToken, GlFilteredSearchSuggestion, - GlDropdownDivider, + GlNewDropdownDivider as GlDropdownDivider, GlLoadingIcon, } from '@gitlab/ui'; import { debounce } from 'lodash'; @@ -102,14 +102,14 @@ export default { @input="searchLabels" > <template #view-token="{ inputValue, cssClasses, listeners }"> - <gl-token variant="search-value" :class="cssClasses" :style="containerStyle" v-on="listeners"> - ~{{ activeLabel ? activeLabel.title : inputValue }} - </gl-token> + <gl-token variant="search-value" :class="cssClasses" :style="containerStyle" v-on="listeners" + >~{{ activeLabel ? activeLabel.title : inputValue }}</gl-token + > </template> <template #suggestions> - <gl-filtered-search-suggestion :value="$options.noLabel"> - {{ __('No label') }} - </gl-filtered-search-suggestion> + <gl-filtered-search-suggestion :value="$options.noLabel">{{ + __('No label') + }}</gl-filtered-search-suggestion> <gl-dropdown-divider /> <gl-loading-icon v-if="loading" /> <template v-else> diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue index 2665bb4aa92..2625fcc9d09 100644 --- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue +++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue @@ -105,7 +105,7 @@ export default { </template> </section> - <section v-if="$slots.default" class="header-action-buttons"> + <section v-if="$slots.default" data-testid="headerButtons" class="gl-display-flex"> <slot></slot> </section> <gl-deprecated-button diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 6cd8ea7aa3a..5577d73bee7 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -1052,13 +1052,6 @@ button.mini-pipeline-graph-dropdown-toggle { .text-center { padding-top: 12px; } - - .header-action-buttons { - .btn, - a { - margin-left: 10px; - } - } } .pipelines-container .top-area .nav-controls > .btn:last-child { diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index f79df25175b..d4d6583312c 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -143,8 +143,8 @@ .group-home-panel, .project-home-panel { - padding-top: $gl-padding; - padding-bottom: $gl-padding; + margin-top: $gl-padding; + margin-bottom: $gl-padding; .home-panel-avatar { width: $home-panel-title-row-height; diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb index 2f5dc09be4a..7cb19fc7e58 100644 --- a/app/controllers/concerns/send_file_upload.rb +++ b/app/controllers/concerns/send_file_upload.rb @@ -18,7 +18,11 @@ module SendFileUpload send_params.merge!(filename: attachment, disposition: disposition) end - if file_upload.file_storage? + if image_scaling_request?(file_upload) + location = file_upload.file_storage? ? file_upload.path : file_upload.url + headers.store(*Gitlab::Workhorse.send_scaled_image(location, params[:width].to_i)) + head :ok + elsif file_upload.file_storage? send_file file_upload.path, send_params elsif file_upload.class.proxy_download_enabled? || proxy headers.store(*Gitlab::Workhorse.send_url(file_upload.url(**redirect_params))) @@ -37,4 +41,19 @@ module SendFileUpload "application/octet-stream" end end + + private + + def image_scaling_request?(file_upload) + avatar_image_upload?(file_upload) && valid_image_scaling_width? && current_user && + Feature.enabled?(:dynamic_image_resizing, current_user) + end + + def avatar_image_upload?(file_upload) + file_upload.try(:image?) && file_upload.try(:mounted_as)&.to_sym == :avatar + end + + def valid_image_scaling_width? + Avatarable::ALLOWED_IMAGE_SCALER_WIDTHS.include?(params[:width]&.to_i) + end end diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 83920f38ab4..29cafbbbdb6 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -75,7 +75,7 @@ class InvitesController < ApplicationController notice = notice.join(' ') + "." store_location_for :user, request.fullpath - redirect_to new_user_session_path, notice: notice + redirect_to new_user_session_path(invite_email: member.invite_email), notice: notice end def invite_details diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index dd438d09f68..f82212591b6 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -25,6 +25,7 @@ class SessionsController < Devise::SessionsController before_action :store_unauthenticated_sessions, only: [:new] before_action :save_failed_login, if: :action_new_and_failed_login? before_action :load_recaptcha + before_action :set_invite_params, only: [:new] after_action :log_failed_login, if: :action_new_and_failed_login? after_action :verify_known_sign_in, only: [:create] @@ -291,6 +292,10 @@ class SessionsController < Devise::SessionsController "standard" end end + + def set_invite_params + @invite_email = ActionController::Base.helpers.sanitize(params[:invite_email]) + end end SessionsController.prepend_if_ee('EE::SessionsController') diff --git a/app/graphql/resolvers/group_milestone_resolver.rb b/app/graphql/resolvers/group_milestones_resolver.rb index 26bbb2ca21c..8d34cea4fa1 100644 --- a/app/graphql/resolvers/group_milestone_resolver.rb +++ b/app/graphql/resolvers/group_milestones_resolver.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true module Resolvers - class GroupMilestoneResolver < MilestoneResolver + class GroupMilestonesResolver < MilestonesResolver argument :include_descendants, GraphQL::BOOLEAN_TYPE, - required: false, - description: 'Also return milestones in all subgroups and subprojects' + required: false, + description: 'Also return milestones in all subgroups and subprojects' private diff --git a/app/graphql/resolvers/milestone_resolver.rb b/app/graphql/resolvers/milestones_resolver.rb index f4ab7507b12..5f80506c01b 100644 --- a/app/graphql/resolvers/milestone_resolver.rb +++ b/app/graphql/resolvers/milestones_resolver.rb @@ -1,17 +1,17 @@ # frozen_string_literal: true module Resolvers - class MilestoneResolver < BaseResolver + class MilestonesResolver < BaseResolver include Gitlab::Graphql::Authorize::AuthorizeResource include TimeFrameArguments argument :ids, [GraphQL::ID_TYPE], - required: false, - description: 'Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1"' + required: false, + description: 'Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1"' argument :state, Types::MilestoneStateEnum, - required: false, - description: 'Filter milestones by state' + required: false, + description: 'Filter milestones by state' type Types::MilestoneType, null: true @@ -35,7 +35,7 @@ module Resolvers end def parent - @parent ||= object.respond_to?(:sync) ? object.sync : object + synchronized_object end def parent_id_parameters(args) diff --git a/app/graphql/resolvers/project_milestone_resolver.rb b/app/graphql/resolvers/project_milestones_resolver.rb index 0b5d5996e04..976fc300b87 100644 --- a/app/graphql/resolvers/project_milestone_resolver.rb +++ b/app/graphql/resolvers/project_milestones_resolver.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true module Resolvers - class ProjectMilestoneResolver < MilestoneResolver + class ProjectMilestonesResolver < MilestonesResolver argument :include_ancestors, GraphQL::BOOLEAN_TYPE, - required: false, - description: "Also return milestones in the project's parent group and its ancestors" + required: false, + description: "Also return milestones in the project's parent group and its ancestors" private diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb index d774c984068..bafa12e2778 100644 --- a/app/graphql/types/group_type.rb +++ b/app/graphql/types/group_type.rb @@ -51,7 +51,7 @@ module Types field :milestones, Types::MilestoneType.connection_type, null: true, description: 'Milestones of the group', - resolver: Resolvers::GroupMilestoneResolver + resolver: Resolvers::GroupMilestonesResolver field :boards, Types::BoardType.connection_type, diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb index fe5c64c4937..4bf6be0181a 100644 --- a/app/graphql/types/project_type.rb +++ b/app/graphql/types/project_type.rb @@ -150,7 +150,7 @@ module Types field :milestones, Types::MilestoneType.connection_type, null: true, description: 'Milestones of the project', - resolver: Resolvers::ProjectMilestoneResolver + resolver: Resolvers::ProjectMilestonesResolver field :project_members, Types::ProjectMemberType.connection_type, diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index b4cbd96bfdb..c04f4da70cf 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -47,6 +47,15 @@ module Types null: false, description: 'Fields related to design management' + field :milestone, ::Types::MilestoneType, + null: true, + description: 'Find a milestone', + resolve: -> (_obj, args, _ctx) { GitlabSchema.find_by_gid(args[:id]) } do + argument :id, ::Types::GlobalIDType[Milestone], + required: true, + description: 'Find a milestone by its ID' + end + field :user, Types::UserType, null: true, description: 'Find a user', diff --git a/app/graphql/types/snippet_type.rb b/app/graphql/types/snippet_type.rb index 73ca3425ded..db98e62c10a 100644 --- a/app/graphql/types/snippet_type.rb +++ b/app/graphql/types/snippet_type.rb @@ -66,7 +66,8 @@ module Types field :blob, type: Types::Snippets::BlobType, description: 'Snippet blob', calls_gitaly: true, - null: false + null: false, + deprecated: { reason: 'Use `blobs`', milestone: '13.3' } field :blobs, type: [Types::Snippets::BlobType], description: 'Snippet blobs', diff --git a/app/helpers/active_sessions_helper.rb b/app/helpers/active_sessions_helper.rb index 8fb23f99cb3..b80152777a8 100644 --- a/app/helpers/active_sessions_helper.rb +++ b/app/helpers/active_sessions_helper.rb @@ -20,6 +20,6 @@ module ActiveSessionsHelper 'monitor-o' end - sprite_icon(icon_name, size: 16, css_class: 'gl-mt-2') + sprite_icon(icon_name, css_class: 'gl-mt-2') end end diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb index 7bf3795d73a..0ba03cd90ea 100644 --- a/app/helpers/dashboard_helper.rb +++ b/app/helpers/dashboard_helper.rb @@ -40,7 +40,7 @@ module DashboardHelper end) if doc_href.present? - link_to_doc = link_to(sprite_icon('question', size: 16), doc_href, + link_to_doc = link_to(sprite_icon('question'), doc_href, class: 'gl-ml-2', title: _('Documentation'), target: '_blank', rel: 'noopener noreferrer') diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 095a5392aa1..0b859a39c4f 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -205,7 +205,7 @@ module IssuablesHelper author_output end - output << content_tag(:span, (sprite_icon('first-contribution', size: 16, css_class: 'gl-icon gl-vertical-align-middle') if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!')) + output << content_tag(:span, (sprite_icon('first-contribution', css_class: 'gl-icon gl-vertical-align-middle') if issuable.first_contribution?), class: 'has-tooltip gl-ml-2', title: _('1st contribution!')) output << content_tag(:span, (issuable.task_status if issuable.tasks?), id: "task_status", class: "d-none d-sm-none d-md-inline-block gl-ml-3") output << content_tag(:span, (issuable.task_status_short if issuable.tasks?), id: "task_status_short", class: "d-md-none") diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 61fe075303c..55170cbfa6b 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -41,7 +41,7 @@ module IssuesHelper end def confidential_icon(issue) - sprite_icon('eye-slash', size: 16, css_class: 'gl-vertical-align-text-bottom') if issue.confidential? + sprite_icon('eye-slash', css_class: 'gl-vertical-align-text-bottom') if issue.confidential? end def award_user_list(awards, current_user, limit: 10) diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 417aeb219f9..de6990041a6 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -238,7 +238,7 @@ module SortingHelper end link_to(url, type: 'button', class: link_class, title: s_('SortOptions|Sort direction')) do - sprite_icon(icon, size: 16) + sprite_icon(icon) end end diff --git a/app/helpers/wiki_helper.rb b/app/helpers/wiki_helper.rb index cf2d2d178e1..ad33ac66f38 100644 --- a/app/helpers/wiki_helper.rb +++ b/app/helpers/wiki_helper.rb @@ -80,7 +80,7 @@ module WikiHelper link_to(wiki_path(wiki, action: :pages, sort: sort, direction: reversed_direction), type: 'button', class: link_class, title: _('Sort direction')) do - sprite_icon("sort-#{icon_class}", size: 16) + sprite_icon("sort-#{icon_class}") end end diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb index 60de20c3b31..0dd55ab67b5 100644 --- a/app/models/concerns/avatarable.rb +++ b/app/models/concerns/avatarable.rb @@ -3,6 +3,17 @@ module Avatarable extend ActiveSupport::Concern + ALLOWED_IMAGE_SCALER_WIDTHS = [ + 400, + 200, + 64, + 48, + 40, + 26, + 20, + 16 + ].freeze + included do prepend ShadowMethods include ObjectStorage::BackgroundMove diff --git a/app/presenters/gitlab/blame_presenter.rb b/app/presenters/gitlab/blame_presenter.rb index db2fc52a88b..3c581d4b115 100644 --- a/app/presenters/gitlab/blame_presenter.rb +++ b/app/presenters/gitlab/blame_presenter.rb @@ -76,7 +76,7 @@ module Gitlab end def versions_sprite_icon - @versions_sprite_icon ||= sprite_icon('doc-versions', size: 16, css_class: 'doc-versions align-text-bottom') + @versions_sprite_icon ||= sprite_icon('doc-versions', css_class: 'doc-versions align-text-bottom') end end end diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb index 4e8dae1d508..86fd405812e 100644 --- a/app/presenters/project_presenter.rb +++ b/app/presenters/project_presenter.rb @@ -16,7 +16,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated MAX_TOPICS_TO_SHOW = 3 def statistic_icon(icon_name = 'plus-square-o') - sprite_icon(icon_name, size: 16, css_class: 'icon gl-mr-2') + sprite_icon(icon_name, css_class: 'icon gl-mr-2') end def statistics_anchors(show_auto_devops_callout:) diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml index a62197745cb..7f0e9faa59e 100644 --- a/app/views/admin/application_settings/integrations.html.haml +++ b/app/views/admin/application_settings/integrations.html.haml @@ -5,9 +5,9 @@ - if Feature.enabled?(:instance_level_integrations) - if show_admin_integrations_moved? .gl-alert.gl-alert-info.js-admin-integrations-moved.mt-3{ role: 'alert', data: { feature_id: UserCalloutsHelper::ADMIN_INTEGRATIONS_MOVED, dismiss_endpoint: user_callouts_path } } - = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') } - = sprite_icon('close', size: 16, css_class: 'gl-icon') + = sprite_icon('close', css_class: 'gl-icon') .gl-alert-body %h4.gl-alert-title= s_('AdminSettings|Some settings have moved') = html_escape_once(s_('AdminSettings|Elasticsearch, PlantUML, Slack application, Third party offers, Snowplow, Amazon EKS have moved to Settings > General.')).html_safe diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml index 79d758cf10b..8a937bd66cf 100644 --- a/app/views/admin/broadcast_messages/_form.html.haml +++ b/app/views/admin/broadcast_messages/_form.html.haml @@ -1,5 +1,5 @@ .broadcast-message.broadcast-banner-message.alert-warning.js-broadcast-banner-message-preview.mt-2{ style: broadcast_message_style(@broadcast_message), class: ('hidden' unless @broadcast_message.banner? ) } - = sprite_icon('bullhorn', size: 16, css_class:'vertical-align-text-top') + = sprite_icon('bullhorn', css_class:'vertical-align-text-top') .js-broadcast-message-preview - if @broadcast_message.message.present? = render_broadcast_message(@broadcast_message) @@ -7,7 +7,7 @@ Your message here .d-flex.justify-content-center .broadcast-message.broadcast-notification-message.preview.js-broadcast-notification-message-preview.mt-2{ class: ('hidden' unless @broadcast_message.notification? ) } - = sprite_icon('bullhorn', size: 16, css_class:'vertical-align-text-top') + = sprite_icon('bullhorn', css_class:'vertical-align-text-top') .js-broadcast-message-preview - if @broadcast_message.message.present? = render_broadcast_message(@broadcast_message) diff --git a/app/views/admin/groups/_group.html.haml b/app/views/admin/groups/_group.html.haml index fc1d5397e82..0cbea326255 100644 --- a/app/views/admin/groups/_group.html.haml +++ b/app/views/admin/groups/_group.html.haml @@ -22,11 +22,11 @@ = render_if_exists 'admin/groups/marked_for_deletion_badge', group: group, css_class: 'gl-ml-5' %span.gl-ml-5 - = sprite_icon('bookmark', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('bookmark', css_class: 'gl-vertical-align-text-bottom') = number_with_delimiter(group.projects.count) %span.gl-ml-5 - = sprite_icon('users', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('users', css_class: 'gl-vertical-align-text-bottom') = number_with_delimiter(group.users.count) %span.gl-ml-5.visibility-icon.has-tooltip{ data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group) } diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml index cf7bf13155a..0bbe73d6f7e 100644 --- a/app/views/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -66,7 +66,7 @@ .btn-group.table-action-buttons .btn-group = link_to admin_runner_path(runner), class: 'btn btn-default has-tooltip', title: _('Edit'), ref: 'tooltip', aria: { label: _('Edit') }, data: { placement: 'top', container: 'body'} do - = sprite_icon('pencil', size: 16) + = sprite_icon('pencil') .btn-group - if runner.active? = link_to [:pause, :admin, runner], method: :get, class: 'btn btn-default btn-svg has-tooltip', title: _('Pause'), ref: 'tooltip', aria: { label: _('Pause') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do diff --git a/app/views/admin/users/_user_listing_note.html.haml b/app/views/admin/users/_user_listing_note.html.haml index b6c9bc43339..e5c43259b79 100644 --- a/app/views/admin/users/_user_listing_note.html.haml +++ b/app/views/admin/users/_user_listing_note.html.haml @@ -1,3 +1,3 @@ - if user.note.present? %span.has-tooltip.user-note{ title: user.note } - = sprite_icon('document', size: 16, css_class: 'gl-vertical-align-middle') + = sprite_icon('document', css_class: 'gl-vertical-align-middle') diff --git a/app/views/clusters/clusters/_banner.html.haml b/app/views/clusters/clusters/_banner.html.haml index e9ad0c6a4e0..3461831eda2 100644 --- a/app/views/clusters/clusters/_banner.html.haml +++ b/app/views/clusters/clusters/_banner.html.haml @@ -7,16 +7,16 @@ %span.gl-ml-2= s_('ClusterIntegration|Kubernetes cluster is being created...') .hidden.row.js-cluster-api-unreachable.gl-alert.gl-alert-warning{ role: 'alert' } - = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') %button.js-close-banner.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') } - = sprite_icon('close', size: 16, css_class: 'gl-icon') + = sprite_icon('close', css_class: 'gl-icon') .gl-alert-body = s_('ClusterIntegration|Your cluster API is unreachable. Please ensure your API URL is correct.') .hidden.js-cluster-authentication-failure.js-cluster-api-unreachable.gl-alert.gl-alert-warning{ role: 'alert' } - = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') %button.js-close-banner.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') } - = sprite_icon('close', size: 16, css_class: 'gl-icon') + = sprite_icon('close', css_class: 'gl-icon') .gl-alert-body = s_('ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid.') diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml index 3869ca6591c..54f6fa91cf1 100644 --- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml +++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml @@ -3,10 +3,9 @@ %button.close.js-close{ type: "button" } × .gcp-signup-offer--content .gcp-signup-offer--icon.gl-mr-3 - = sprite_icon("information", size: 16) + = sprite_icon("information") .gcp-signup-offer--copy %h4= s_('ClusterIntegration|Did you know?') %p= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link } %a.btn.btn-default{ href: 'https://cloud.google.com/partners/partnercredit/?pcn_code=0014M00001h35gDQAQ#contact-form', target: '_blank', rel: 'noopener noreferrer' } = s_("ClusterIntegration|Apply for credit") - diff --git a/app/views/dashboard/_activities.html.haml b/app/views/dashboard/_activities.html.haml index 167aa0a2e59..d617ee0e4cc 100644 --- a/app/views/dashboard/_activities.html.haml +++ b/app/views/dashboard/_activities.html.haml @@ -2,7 +2,7 @@ = render 'shared/event_filter' .controls = link_to dashboard_projects_path(rss_url_options), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-flex has-tooltip', title: 'Subscribe' do - = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon', size: 16) + = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon') .content_list .loading diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml index 6e9efcb0597..8c0ca6d4345 100644 --- a/app/views/devise/sessions/_new_base.html.haml +++ b/app/views/devise/sessions/_new_base.html.haml @@ -1,7 +1,7 @@ = form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: 'new_user gl-show-field-errors', 'aria-live' => 'assertive'}) do |f| .form-group = f.label _('Username or email'), for: 'user_login', class: 'label-bold' - = f.text_field :login, class: 'form-control top', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', required: true, title: _('This field is required.'), data: { qa_selector: 'login_field' } + = f.text_field :login, value: @invite_email, class: 'form-control top', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off', required: true, title: _('This field is required.'), data: { qa_selector: 'login_field' } .form-group = f.label :password, class: 'label-bold' = f.password_field :password, class: 'form-control bottom', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' } diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index 0735702ae5f..0da51d460e3 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -19,7 +19,7 @@ %p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking username availability...') .form-group = f.label :email, class: 'label-bold' - = f.email_field :email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.") + = f.email_field :email, value: @invite_email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.") .form-group = f.label :email_confirmation, class: 'label-bold' = f.email_field :email_confirmation, class: "form-control middle", data: { qa_selector: 'new_user_email_confirmation_field' }, required: true, title: _("Please retype the email address.") diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml index fd86d07fc86..f36f30d3638 100644 --- a/app/views/explore/groups/index.html.haml +++ b/app/views/explore/groups/index.html.haml @@ -12,7 +12,7 @@ - if cookies[:explore_groups_landing_dismissed] != 'true' .explore-groups.landing.content-block.js-explore-groups-landing.hide - %button.dismiss-button{ type: 'button', 'aria-label' => _('Dismiss') }= sprite_icon('close', size: 16) + %button.dismiss-button{ type: 'button', 'aria-label' => _('Dismiss') }= sprite_icon('close') .svg-container = custom_icon('icon_explore_groups_splash') .inner-content diff --git a/app/views/groups/_activities.html.haml b/app/views/groups/_activities.html.haml index 84cf4b31bd7..769455dc951 100644 --- a/app/views/groups/_activities.html.haml +++ b/app/views/groups/_activities.html.haml @@ -2,9 +2,8 @@ = render 'shared/event_filter', show_group_events: @group.supports_events? .controls = link_to group_path(@group, rss_url_options), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-flex has-tooltip' , title: 'Subscribe' do - = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon', size: 16) + = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon') .content_list .loading .spinner.spinner-md - diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml index 5513849be3d..ef803a36e79 100644 --- a/app/views/import/gitlab/status.html.haml +++ b/app/views/import/gitlab/status.html.haml @@ -1,7 +1,7 @@ - page_title _("GitLab.com import") - header_title _("Projects"), root_path %h3.page-title - = sprite_icon('heart', size: 16, css_class: 'gl-vertical-align-middle') + = sprite_icon('heart', css_class: 'gl-vertical-align-middle') = _('Import projects from GitLab.com') = render 'import/githubish_status', provider: 'gitlab', filterable: false diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index b667d2aa0d7..cd477c085f9 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -3,7 +3,7 @@ %h3.page-title.d-flex .gl-display-flex.gl-align-items-center.gl-justify-content-center - = sprite_icon('tanuki', size: 16, css_class: 'gl-mr-2') + = sprite_icon('tanuki', css_class: 'gl-mr-2') = _('Import an exported GitLab project') %hr diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml index 1424b9a7585..be3f2fd74e4 100644 --- a/app/views/layouts/_flash.html.haml +++ b/app/views/layouts/_flash.html.haml @@ -6,8 +6,8 @@ .js-toast-message{ data: { message: value } } - elsif value %div{ class: "flash-#{key} mb-2" } - = sprite_icon(icons[key], size: 16, css_class: 'align-middle mr-1') unless icons[key].nil? + = sprite_icon(icons[key], css_class: 'align-middle mr-1') unless icons[key].nil? %span= value - if %w(alert notice success).include?(key) %div{ class: "close-icon-wrapper js-close-icon" } - = sprite_icon('close', size: 16, css_class: 'close-icon') + = sprite_icon('close', css_class: 'close-icon') diff --git a/app/views/layouts/_search.html.haml b/app/views/layouts/_search.html.haml index 81fe0798bd1..4c87920ad89 100644 --- a/app/views/layouts/_search.html.haml +++ b/app/views/layouts/_search.html.haml @@ -20,8 +20,8 @@ %a = _('Loading...') = dropdown_loading - = sprite_icon('search', size: 16, css_class: 'search-icon') - = sprite_icon('close', size: 16, css_class: 'clear-icon js-clear-input') + = sprite_icon('search', css_class: 'search-icon') + = sprite_icon('close', css_class: 'clear-icon js-clear-input') = hidden_field_tag :group_id, search_context.for_group? ? search_context.group.id : '', class: 'js-search-group-options', data: search_context.group_metadata = hidden_field_tag :project_id, search_context.for_project? ? search_context.project.id : '', id: 'search_project_id', class: 'js-search-project-options', data: search_context.project_metadata diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 0d21f224a8a..a191eb8cbdb 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -32,32 +32,32 @@ = render 'layouts/search' unless current_controller?(:search) %li.nav-item.d-inline-block.d-lg-none = link_to search_context.search_url, title: _('Search'), aria: { label: _('Search') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do - = sprite_icon('search', size: 16) + = sprite_icon('search') - if header_link?(:issues) = nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do = link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues', aria: { label: _('Issues') }, data: { qa_selector: 'issues_shortcut_button', toggle: 'tooltip', placement: 'bottom', container: 'body' } do - = sprite_icon('issues', size: 16) + = sprite_icon('issues') - issues_count = assigned_issuables_count(:issues) %span.badge.badge-pill.issues-count.green-badge{ class: ('hidden' if issues_count == 0) } = number_with_delimiter(issues_count) - if header_link?(:merge_requests) = nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter" }) do = link_to assigned_mrs_dashboard_path, title: _('Merge requests'), class: 'dashboard-shortcuts-merge_requests', aria: { label: _('Merge requests') }, data: { qa_selector: 'merge_requests_shortcut_button', toggle: 'tooltip', placement: 'bottom', container: 'body' } do - = sprite_icon('git-merge', size: 16) + = sprite_icon('git-merge') - merge_requests_count = assigned_issuables_count(:merge_requests) %span.badge.badge-pill.merge-requests-count{ class: ('hidden' if merge_requests_count == 0) } = number_with_delimiter(merge_requests_count) - if header_link?(:todos) = nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do = link_to dashboard_todos_path, title: _('To-Do List'), aria: { label: _('To-Do List') }, class: 'shortcuts-todos', data: { qa_selector: 'todos_shortcut_button', toggle: 'tooltip', placement: 'bottom', container: 'body' } do - = sprite_icon('todo-done', size: 16) + = sprite_icon('todo-done') %span.badge.badge-pill.todos-count{ class: ('hidden' if todos_pending_count == 0) } = todos_count_format(todos_pending_count) %li.nav-item.header-help.dropdown.d-none.d-md-block = link_to help_path, class: 'header-help-dropdown-toggle', data: { toggle: "dropdown" } do %span.gl-sr-only = s_('Nav|Help') - = sprite_icon('question', size: 16) + = sprite_icon('question') = sprite_icon('angle-down', css_class: 'caret-down') .dropdown-menu.dropdown-menu-right = render 'layouts/header/help_dropdown' diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml index 4bfac76ec5b..0c989242194 100644 --- a/app/views/layouts/header/_new_dropdown.haml +++ b/app/views/layouts/header/_new_dropdown.haml @@ -1,6 +1,6 @@ %li.header-new.dropdown{ data: { track_label: "new_dropdown", track_event: "click_dropdown", track_value: "" } } = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip qa-new-menu-toggle", id: "js-onboarding-new-project-link", title: _("New..."), ref: 'tooltip', aria: { label: _("New...") }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static' } do - = sprite_icon('plus-square', size: 16) + = sprite_icon('plus-square') = sprite_icon('angle-down', css_class: 'caret-down') .dropdown-menu.dropdown-menu-right %ul diff --git a/app/views/profiles/gpg_keys/_key.html.haml b/app/views/profiles/gpg_keys/_key.html.haml index dd2de252ff7..e05f121c5d9 100644 --- a/app/views/profiles/gpg_keys/_key.html.haml +++ b/app/views/profiles/gpg_keys/_key.html.haml @@ -1,6 +1,6 @@ %li.key-list-item .float-left.gl-mr-3 - = sprite_icon('key', size: 16, css_class: "settings-list-icon d-none d-sm-block gl-mt-4") + = sprite_icon('key', css_class: "settings-list-icon d-none d-sm-block gl-mt-4") .key-list-item-info - key.emails_with_verified_status.map do |email, verified| = render partial: 'shared/email_with_badge', locals: { email: email, verified: verified } diff --git a/app/views/profiles/keys/_key.html.haml b/app/views/profiles/keys/_key.html.haml index c9ab7b6fbd3..02b45853aa0 100644 --- a/app/views/profiles/keys/_key.html.haml +++ b/app/views/profiles/keys/_key.html.haml @@ -3,12 +3,12 @@ - if key.valid? - if key.expired? %span.d-inline-block.has-tooltip{ title: s_('Profiles|Your key has expired') } - = sprite_icon('warning-solid', size: 16, css_class: 'settings-list-icon d-none d-sm-block') + = sprite_icon('warning-solid', css_class: 'settings-list-icon d-none d-sm-block') - else - = sprite_icon('key', size: 16, css_class: 'settings-list-icon d-none d-sm-block ') + = sprite_icon('key', css_class: 'settings-list-icon d-none d-sm-block ') - else %span.d-inline-block.has-tooltip{ title: key.errors.full_messages.join(', ') } - = sprite_icon('warning-solid', size: 16, css_class: 'settings-list-icon d-none d-sm-block') + = sprite_icon('warning-solid', css_class: 'settings-list-icon d-none d-sm-block') .key-list-item-info.w-100.float-none = link_to path_to_key(key, is_admin), class: "title" do @@ -28,4 +28,4 @@ - if key.can_delete? = link_to path_to_key(key, is_admin), data: { confirm: _('Are you sure?')}, method: :delete, class: "btn btn-transparent gl-ml-3 align-baseline" do %span.sr-only= _('Remove') - = sprite_icon('remove', size: 16) + = sprite_icon('remove') diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml index 26ff025b90b..c47ca81c431 100644 --- a/app/views/projects/_activity.html.haml +++ b/app/views/projects/_activity.html.haml @@ -5,7 +5,7 @@ = render 'shared/event_filter' .controls.gl-display-flex = link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn gl-button btn-default btn-icon d-none d-sm-inline-flex has-tooltip' do - = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon', size: 16) + = sprite_icon('rss', css_class: 'qa-rss-icon gl-icon') - if is_project_overview && can?(current_user, :download_code, @project) .project-clone-holder.d-none.d-md-inline-flex.gl-ml-2 = render "projects/buttons/clone", dropdown_class: 'dropdown-menu-right' diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 653b1431757..94a2bdb3bcb 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -24,7 +24,7 @@ = render 'shared/members/access_request_links', source: @project - if @project.tag_list.present? %span.home-panel-topic-list.mt-2.w-100.d-inline-flex - = sprite_icon('tag', size: 16, css_class: 'icon gl-mr-2') + = sprite_icon('tag', css_class: 'icon gl-mr-2') - @project.topics_to_show.each do |topic| - project_topics_classes = "badge badge-pill badge-secondary gl-mr-2" diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml index 0e4fcb8a191..4769a7c89c2 100644 --- a/app/views/projects/_import_project_pane.html.haml +++ b/app/views/projects/_import_project_pane.html.haml @@ -57,7 +57,7 @@ - if git_import_enabled? %div %button.btn.btn-svg.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' }, **tracking_attrs(track_label, 'click_button', 'repo_url') } - = sprite_icon('link', size: 16, css_class: 'gl-icon') + = sprite_icon('link', css_class: 'gl-icon') = _('Repo by URL') - if manifest_import_enabled? diff --git a/app/views/projects/_visibility_modal.html.haml b/app/views/projects/_visibility_modal.html.haml index 465a280c319..c6e1ab079e6 100644 --- a/app/views/projects/_visibility_modal.html.haml +++ b/app/views/projects/_visibility_modal.html.haml @@ -7,7 +7,7 @@ .modal-header %h3.page-title= _('Reduce this project’s visibility?') %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') } - %span{ "aria-hidden": true }= sprite_icon("close", size: 16) + %span{ "aria-hidden": true }= sprite_icon("close") .modal-body %p - if @project.group diff --git a/app/views/projects/blob/viewers/_changelog.html.haml b/app/views/projects/blob/viewers/_changelog.html.haml index c9d64d5f62e..80ead53beff 100644 --- a/app/views/projects/blob/viewers/_changelog.html.haml +++ b/app/views/projects/blob/viewers/_changelog.html.haml @@ -1,4 +1,4 @@ -= sprite_icon('history', size: 16, css_class: 'gl-mr-1 gl-vertical-align-text-bottom') += sprite_icon('history', css_class: 'gl-mr-1 gl-vertical-align-text-bottom') = succeed '.' do To find the state of this project's repository at the time of any of these versions, check out = link_to "the tags", project_tags_path(viewer.project) diff --git a/app/views/projects/blob/viewers/_license.html.haml b/app/views/projects/blob/viewers/_license.html.haml index 7ac0e7bb579..d2bd90a898a 100644 --- a/app/views/projects/blob/viewers/_license.html.haml +++ b/app/views/projects/blob/viewers/_license.html.haml @@ -1,6 +1,6 @@ - license = viewer.license -= sprite_icon('scale', size: 16) += sprite_icon('scale') This project is licensed under the = succeed '.' do %strong= license.name diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index d915f4755cc..28b5dc0cc67 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -27,7 +27,7 @@ = search_field_tag :search, params[:search], { placeholder: _('Search by message'), id: 'commits-search', class: 'form-control search-text-input input-short gl-mt-3 gl-sm-mt-0 gl-min-w-full', spellcheck: false } .control.d-none.d-md-block = link_to project_commits_path(@project, @ref, rss_url_options), title: _("Commits feed"), class: 'btn btn-svg' do - = sprite_icon('rss', css_class: 'qa-rss-icon', size: 16) + = sprite_icon('rss', css_class: 'qa-rss-icon') = render_if_exists 'projects/commits/mirror_status' diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml index d10fa69ff47..768acac96c0 100644 --- a/app/views/projects/compare/_form.html.haml +++ b/app/views/projects/compare/_form.html.haml @@ -10,7 +10,7 @@ = hidden_field_tag :to, params[:to] = button_tag type: 'button', title: params[:to], class: "btn form-control compare-dropdown-toggle js-compare-dropdown has-tooltip", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to], field_name: :to } do .dropdown-toggle-text.str-truncated.monospace.float-left= params[:to] || _("Select branch/tag") - = sprite_icon('chevron-down', size: 16, css_class: 'float-right') + = sprite_icon('chevron-down', css_class: 'float-right') = render 'shared/ref_dropdown' .compare-ellipsis.inline ... .form-group.dropdown.compare-form-group.from.js-compare-from-dropdown @@ -21,7 +21,7 @@ = hidden_field_tag :from, params[:from] = button_tag type: 'button', title: params[:from], class: "btn form-control compare-dropdown-toggle js-compare-dropdown has-tooltip", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do .dropdown-toggle-text.str-truncated.monospace.float-left= params[:from] || _("Select branch/tag") - = sprite_icon('chevron-down', size: 16, css_class: 'float-right') + = sprite_icon('chevron-down', css_class: 'float-right') = render 'shared/ref_dropdown' = button_tag s_("CompareBranches|Compare"), class: "btn btn-success commits-compare-btn" diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml index 7395c16c38b..bd023e0442c 100644 --- a/app/views/projects/diffs/_file.html.haml +++ b/app/views/projects/diffs/_file.html.haml @@ -14,7 +14,7 @@ .file-actions.d-none.d-sm-block - if blob&.readable_text? = link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do - = sprite_icon('comment', size: 16) + = sprite_icon('comment') \ - if editable_diff?(diff_file) - link_opts = @merge_request.persisted? ? { from_merge_request_iid: @merge_request.iid } : {} diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml index 0e2a1165ad3..b438fbbf446 100644 --- a/app/views/projects/diffs/_stats.html.haml +++ b/app/views/projects/diffs/_stats.html.haml @@ -22,7 +22,7 @@ - diff_files.each do |diff_file| %li %a.diff-changed-file{ href: "##{hexdigest(diff_file.file_path)}", title: diff_file.new_path } - = sprite_icon(diff_file_changed_icon(diff_file), size: 16, css_class: "#{diff_file_changed_icon_color(diff_file)} diff-file-changed-icon gl-mr-3") + = sprite_icon(diff_file_changed_icon(diff_file), css_class: "#{diff_file_changed_icon_color(diff_file)} diff-file-changed-icon gl-mr-3") %span.diff-changed-file-content.gl-mr-3 - if diff_file.file_path %strong.diff-changed-file-name diff --git a/app/views/projects/forks/error.html.haml b/app/views/projects/forks/error.html.haml index b37dba8b35d..5d527f1bcfb 100644 --- a/app/views/projects/forks/error.html.haml +++ b/app/views/projects/forks/error.html.haml @@ -2,7 +2,7 @@ - if @forked_project && !@forked_project.saved? .alert.alert-danger.alert-block %h4 - = sprite_icon('fork', size: 16) + = sprite_icon('fork') = _("Fork Error!") %p = _("You tried to fork %{link_to_the_project} but it failed for the following reason:").html_safe % { link_to_the_project: link_to_project(@project) } diff --git a/app/views/projects/issues/_alert_moved_from_service_desk.html.haml b/app/views/projects/issues/_alert_moved_from_service_desk.html.haml index a6f969f8b10..9b142b08574 100644 --- a/app/views/projects/issues/_alert_moved_from_service_desk.html.haml +++ b/app/views/projects/issues/_alert_moved_from_service_desk.html.haml @@ -3,8 +3,8 @@ - service_desk_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: service_desk_link_url } .hide.gl-alert.gl-alert-warning.js-alert-moved-from-service-desk-warning.gl-mt-5{ role: 'alert' } - = sprite_icon('warning', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('warning', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') } - = sprite_icon('close', size: 16, css_class: 'gl-icon') + = sprite_icon('close', css_class: 'gl-icon') .gl-alert-body.gl-mr-3 = s_('This project does not have %{service_desk_link_start}Service Desk%{service_desk_link_end} enabled, so the user who created the issue will no longer receive email notifications about new activity.').html_safe % { service_desk_link_start: service_desk_link_start, service_desk_link_end: '</a>'.html_safe } diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml index 0995e7d4fac..96d9870514c 100644 --- a/app/views/projects/issues/_issue.html.haml +++ b/app/views/projects/issues/_issue.html.haml @@ -30,7 +30,7 @@ %span.issuable-milestone.d-none.d-sm-inline-block = link_to project_issues_path(issue.project, milestone_title: issue.milestone.title), data: { html: 'true', toggle: 'tooltip', title: milestone_tooltip_due_date(issue.milestone) } do - = sprite_icon('clock', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('clock', css_class: 'gl-vertical-align-text-bottom') = issue.milestone.title - if issue.due_date %span.issuable-due-date.d-none.d-sm-inline-block.has-tooltip{ class: "#{'cred' if issue.overdue?}", title: _('Due date') } diff --git a/app/views/projects/issues/_issue_estimate.html.haml b/app/views/projects/issues/_issue_estimate.html.haml index 46797d0f1a0..c49bf626f4e 100644 --- a/app/views/projects/issues/_issue_estimate.html.haml +++ b/app/views/projects/issues/_issue_estimate.html.haml @@ -3,5 +3,5 @@ - if issue.time_estimate > 0 %span.issuable-estimate.d-none.d-sm-inline-block.has-tooltip{ data: { container: 'body', qa_selector: 'issuable_estimate' }, title: _('Estimate') } - = sprite_icon('timer', size: 16, css_class: 'issue-estimate-icon') + = sprite_icon('timer', css_class: 'issue-estimate-icon') = Gitlab::TimeTrackingFormatter.output(issue.time_estimate) diff --git a/app/views/projects/issues/export_csv/_modal.html.haml b/app/views/projects/issues/export_csv/_modal.html.haml index 57a18ad5daa..793e43da935 100644 --- a/app/views/projects/issues/export_csv/_modal.html.haml +++ b/app/views/projects/issues/export_csv/_modal.html.haml @@ -8,7 +8,7 @@ .svg-content.import-export-svg-container = image_tag 'illustrations/export-import.svg', alt: _('Import/Export illustration'), class: 'illustration' %a.close{ href: '#', 'data-dismiss' => 'modal' } - = sprite_icon('close', size: 16, css_class: 'gl-icon') + = sprite_icon('close', css_class: 'gl-icon') .modal-body .modal-subheader = icon('check', { class: 'checkmark' }) diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index a52f4d151c9..a7817ad5552 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -17,11 +17,11 @@ .detail-page-header .detail-page-header-body .issuable-status-box.status-box.status-box-issue-closed{ class: issue_status_visibility(@issue, status_box: :closed) } - = sprite_icon('mobile-issue-close', size: 16, css_class: 'd-block d-sm-none') + = sprite_icon('mobile-issue-close', css_class: 'd-block d-sm-none') .d-none.d-sm-block = issue_closed_text(@issue, current_user) .issuable-status-box.status-box.status-box-open{ class: issue_status_visibility(@issue, status_box: :open) } - = sprite_icon('issue-open-m', size: 16, css_class: 'd-block d-sm-none') + = sprite_icon('issue-open-m', css_class: 'd-block d-sm-none') %span.d-none.d-sm-block Open .issuable-meta diff --git a/app/views/projects/merge_requests/_approvals_count.html.haml b/app/views/projects/merge_requests/_approvals_count.html.haml index 464cba1bb2d..449e75f26e0 100644 --- a/app/views/projects/merge_requests/_approvals_count.html.haml +++ b/app/views/projects/merge_requests/_approvals_count.html.haml @@ -6,7 +6,7 @@ - final_text = n_("%d approver", "%d approvers", total) % total - final_self_text = n_("%d approver (you've approved)", "%d approvers (you've approved)", total) % total - - approval_icon = sprite_icon((self_approved ? 'approval-solid' : 'approval'), size: 16, css_class: 'align-middle') + - approval_icon = sprite_icon((self_approved ? 'approval-solid' : 'approval'), css_class: 'align-middle') %li.d-none.d-sm-inline-block.has-tooltip.text-success{ title: self_approved ? final_self_text : final_text } = approval_icon diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml index f7b95ce811b..ad0f4d03f9a 100644 --- a/app/views/projects/merge_requests/_merge_request.html.haml +++ b/app/views/projects/merge_requests/_merge_request.html.haml @@ -25,7 +25,7 @@ %span.issuable-milestone.d-none.d-sm-inline-block = link_to project_merge_requests_path(merge_request.project, milestone_title: merge_request.milestone.title), data: { html: 'true', toggle: 'tooltip', title: milestone_tooltip_due_date(merge_request.milestone) } do - = sprite_icon('clock', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('clock', css_class: 'gl-vertical-align-text-bottom') = merge_request.milestone.title - if merge_request.target_project.default_branch != merge_request.target_branch %span.project-ref-path.has-tooltip{ title: _('Target branch') } @@ -45,13 +45,13 @@ = _('MERGED') - elsif merge_request.closed? %li.issuable-status.d-none.d-sm-inline-block - = sprite_icon('cancel', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('cancel', css_class: 'gl-vertical-align-text-bottom') = _('CLOSED') = render 'shared/merge_request_pipeline_status', merge_request: merge_request - if merge_request.open? && merge_request.broken? %li.issuable-pipeline-broken.d-none.d-sm-flex = link_to merge_request_path(merge_request), class: "has-tooltip", title: _('Cannot be merged automatically') do - = sprite_icon('warning-solid', size: 16) + = sprite_icon('warning-solid') - if merge_request.assignees.any? %li.d-flex = render 'shared/issuable/assignees', project: merge_request.project, issuable: merge_request diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml index a44db035492..cc635809ce0 100644 --- a/app/views/projects/merge_requests/_mr_title.html.haml +++ b/app/views/projects/merge_requests/_mr_title.html.haml @@ -10,7 +10,7 @@ .detail-page-header{ class: ("border-bottom-0 pt-0 pb-0" if mr_tabs_position_enabled?) } .detail-page-header-body .issuable-status-box.status-box{ class: status_box_class(@merge_request) } - = sprite_icon(state_icon_name, size: 16, css_class: 'd-block d-sm-none') + = sprite_icon(state_icon_name, css_class: 'd-block d-sm-none') %span.d-none.d-sm-block = state_human_name diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml index e0ed85dcad7..2f55cce70dc 100644 --- a/app/views/projects/mirrors/_mirror_repos.html.haml +++ b/app/views/projects/mirrors/_mirror_repos.html.haml @@ -36,7 +36,7 @@ = f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror - else .gl-alert.gl-alert-info{ role: 'alert' } - = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') .gl-alert-body = _('Mirror settings are only available to GitLab administrators.') @@ -75,4 +75,3 @@ = clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'), qa_selector: 'copy_public_key_button') = render 'shared/remote_mirror_update_button', remote_mirror: mirror %button.js-delete-mirror.qa-delete-mirror.rspec-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o') - diff --git a/app/views/projects/notes/_actions.html.haml b/app/views/projects/notes/_actions.html.haml index 6cc4c8c1de7..66721a28e62 100644 --- a/app/views/projects/notes/_actions.html.haml +++ b/app/views/projects/notes/_actions.html.haml @@ -1,7 +1,7 @@ - access = note_max_access_for_user(note) - if note.has_special_role?(Note::SpecialRole::FIRST_TIME_CONTRIBUTOR) %span.note-role.note-role-special.has-tooltip{ title: _("This is the author's first Merge Request to this project.") } - = sprite_icon('first-contribution', size: 16, css_class: 'gl-icon gl-vertical-align-top') + = sprite_icon('first-contribution', css_class: 'gl-icon gl-vertical-align-top') - if access.nonzero? %span.note-role.user-access-role= Gitlab::Access.human_access(access) diff --git a/app/views/projects/pages/_list.html.haml b/app/views/projects/pages/_list.html.haml index c116efe521a..af6de10b2a0 100644 --- a/app/views/projects/pages/_list.html.haml +++ b/app/views/projects/pages/_list.html.haml @@ -10,7 +10,7 @@ - if verification_enabled - tooltip, status = domain.unverified? ? [s_('GitLabPages|Unverified'), 'failed'] : [s_('GitLabPages|Verified'), 'success'] .domain-status.ci-status-icon.has-tooltip{ class: "ci-status-icon-#{status}", title: tooltip } - = sprite_icon("status_#{status}", size: 16 ) + = sprite_icon("status_#{status}" ) .domain-name = external_link(domain.url, domain.url) - if domain.certificate diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml index 68e9486f6af..1755a88246b 100644 --- a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml +++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml @@ -34,7 +34,7 @@ = s_('PipelineSchedules|Take ownership') - if can?(current_user, :update_pipeline_schedule, pipeline_schedule) = link_to edit_pipeline_schedule_path(pipeline_schedule), title: _('Edit'), class: 'btn gl-display-flex' do - = sprite_icon('pencil', size: 16) + = sprite_icon('pencil') - if can?(current_user, :admin_pipeline_schedule, pipeline_schedule) = link_to pipeline_schedule_path(pipeline_schedule), title: _('Delete'), method: :delete, class: 'btn btn-remove', data: { confirm: _("Are you sure you want to delete this pipeline schedule?") } do = icon('trash') diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml index 9ca76708557..c54a19b8f61 100644 --- a/app/views/projects/pipelines/_info.html.haml +++ b/app/views/projects/pipelines/_info.html.haml @@ -8,7 +8,7 @@ .info-well .well-segment.pipeline-info .icon-container.gl-vertical-align-text-bottom - = sprite_icon('clock', size: 16) + = sprite_icon('clock') = pluralize @pipeline.total_size, "job" = @pipeline.ref_text - if @pipeline.duration diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml index 6480569b499..74b6e981c00 100644 --- a/app/views/projects/runners/_runner.html.haml +++ b/app/views/projects/runners/_runner.html.haml @@ -7,11 +7,11 @@ - if runner.locked? %span.has-tooltip{ title: _('Locked to current projects') } - = sprite_icon('lock', size: 16) + = sprite_icon('lock') %small.edit-runner = link_to edit_project_runner_path(@project, runner), class: 'btn btn-edit' do - = sprite_icon('pencil', size: 16) + = sprite_icon('pencil') - else %span.commit-sha = runner.short_sha diff --git a/app/views/projects/services/alerts/_top.html.haml b/app/views/projects/services/alerts/_top.html.haml index ff903864370..e3bcb6bd3a0 100644 --- a/app/views/projects/services/alerts/_top.html.haml +++ b/app/views/projects/services/alerts/_top.html.haml @@ -1,7 +1,7 @@ .row .col-lg-12 .gl-alert.gl-alert-info{ role: 'alert' } - = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') .gl-alert-body = _('You can now manage alert endpoint configuration in the Alerts section on the Operations settings page. Fields on this page have been deprecated.') .gl-alert-actions diff --git a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml index cf73a7055c6..7557a00679d 100644 --- a/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_detailed_help.html.haml @@ -7,13 +7,13 @@ 1. = link_to 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands', target: '_blank', rel: 'noopener noreferrer nofollow' do Enable custom slash commands - = sprite_icon('external-link', size: 16) + = sprite_icon('external-link') on your Mattermost installation %li 2. = link_to 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command', target: '_blank', rel: 'noopener noreferrer nofollow' do Add a slash command - = sprite_icon('external-link', size: 16) + = sprite_icon('external-link') in your Mattermost team with these options: %hr diff --git a/app/views/projects/services/mattermost_slash_commands/_help.html.haml b/app/views/projects/services/mattermost_slash_commands/_help.html.haml index cc005dd69b7..1005d9f7990 100644 --- a/app/views/projects/services/mattermost_slash_commands/_help.html.haml +++ b/app/views/projects/services/mattermost_slash_commands/_help.html.haml @@ -6,7 +6,7 @@ = s_("MattermostService|This service allows users to perform common operations on this project by entering slash commands in Mattermost.") = link_to help_page_path('user/project/integrations/mattermost_slash_commands.md'), target: '_blank' do = _("View documentation") - = sprite_icon('external-link', size: 16) + = sprite_icon('external-link') %p.inline = s_("MattermostService|See list of available commands in Mattermost after setting up this service, by entering") %kbd.inline /<trigger> help diff --git a/app/views/projects/services/prometheus/_top.html.haml b/app/views/projects/services/prometheus/_top.html.haml index 56dfa951804..0238a45b75f 100644 --- a/app/views/projects/services/prometheus/_top.html.haml +++ b/app/views/projects/services/prometheus/_top.html.haml @@ -3,7 +3,7 @@ .row .col-lg-12 .gl-alert.gl-alert-info{ role: 'alert' } - = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') .gl-alert-body = s_('AlertSettings|You can now set up alert endpoints for manually configured Prometheus instances in the Alerts section on the Operations settings page. Alert endpoint fields on this page have been deprecated.') .gl-alert-actions diff --git a/app/views/projects/services/slack/_help.haml b/app/views/projects/services/slack/_help.haml index 3cf28bddf88..1fd448020a0 100644 --- a/app/views/projects/services/slack/_help.haml +++ b/app/views/projects/services/slack/_help.haml @@ -3,7 +3,7 @@ .info-well .well-segment - %p= s_('SlackIntegration|This service send notifications about projects\' events to Slack channels. To set up this service:') + %p= s_('SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:') %ol %li = html_escape(s_('SlackIntegration|%{webhooks_link_start}Add an incoming webhook%{webhooks_link_end} in your Slack team. The default channel can be overridden for each event.')) % { webhooks_link_start: webhooks_link_start.html_safe, webhooks_link_end: '</a>'.html_safe } diff --git a/app/views/projects/services/slack_slash_commands/_help.html.haml b/app/views/projects/services/slack_slash_commands/_help.html.haml index 96fef9101d2..86486d95eb7 100644 --- a/app/views/projects/services/slack_slash_commands/_help.html.haml +++ b/app/views/projects/services/slack_slash_commands/_help.html.haml @@ -7,7 +7,7 @@ = s_("SlackService|This service allows users to perform common operations on this project by entering slash commands in Slack.") = link_to help_page_path('user/project/integrations/slack_slash_commands.md'), target: '_blank' do = _("View documentation") - = sprite_icon('external-link', size: 16) + = sprite_icon('external-link') %p.inline = s_("SlackService|See list of available commands in Slack after setting up this service, by entering") %kbd.inline /<command> help @@ -18,7 +18,7 @@ 1. = link_to 'https://my.slack.com/services/new/slash-commands', target: '_blank', rel: 'noreferrer noopener nofollow' do Add a slash command - = sprite_icon('external-link', size: 16) + = sprite_icon('external-link') in your Slack team with these options: %hr diff --git a/app/views/projects/settings/integrations/show.html.haml b/app/views/projects/settings/integrations/show.html.haml index d9068bde847..18c6cb31874 100644 --- a/app/views/projects/settings/integrations/show.html.haml +++ b/app/views/projects/settings/integrations/show.html.haml @@ -4,9 +4,9 @@ - if show_webhooks_moved_alert? .gl-alert.gl-alert-info.js-webhooks-moved-alert.gl-mt-3{ role: 'alert', data: { feature_id: UserCalloutsHelper::WEBHOOKS_MOVED, dismiss_endpoint: user_callouts_path } } - = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title') %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') } - = sprite_icon('close', size: 16, css_class: 'gl-icon') + = sprite_icon('close', css_class: 'gl-icon') .gl-alert-body = _('Webhooks have moved. They can now be found under the Settings menu.') .gl-alert-actions diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 330654d0690..e0def8cf155 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -27,7 +27,7 @@ = link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn', data: { qa_selector: "new_tag_button" } do = s_('TagsPage|New tag') = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn btn-svg d-none d-sm-inline-block has-tooltip' do - = sprite_icon('rss', css_class: 'qa-rss-icon', size: 16) + = sprite_icon('rss', css_class: 'qa-rss-icon') = render_if_exists 'projects/commits/mirror_status' diff --git a/app/views/search/_form.html.haml b/app/views/search/_form.html.haml index de55c72f4f2..b29707d391d 100644 --- a/app/views/search/_form.html.haml +++ b/app/views/search/_form.html.haml @@ -11,7 +11,7 @@ = search_field_tag :search, params[:search], placeholder: _("Search for projects, issues, etc."), class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false = icon("search", class: "search-icon") %button.search-clear.js-search-clear{ class: ("hidden" if !params[:search].present?), type: "button", tabindex: "-1" } - = sprite_icon('clear', size: 16) + = sprite_icon('clear') %span.sr-only = _("Clear search") - unless params[:snippets].eql? 'true' diff --git a/app/views/search/results/_note.html.haml b/app/views/search/results/_note.html.haml index b67bc71941a..a83b003a516 100644 --- a/app/views/search/results/_note.html.haml +++ b/app/views/search/results/_note.html.haml @@ -4,7 +4,7 @@ .search-result-row %h5.note-search-caption.str-truncated - = sprite_icon('comment', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('comment', css_class: 'gl-vertical-align-text-bottom') = link_to_member(project, note.author, avatar: false) - link_to_project = link_to(project.full_name, project) = _("commented on %{link_to_project}").html_safe % { link_to_project: link_to_project } diff --git a/app/views/shared/_broadcast_message.html.haml b/app/views/shared/_broadcast_message.html.haml index 3e889900981..e313946a968 100644 --- a/app/views/shared/_broadcast_message.html.haml +++ b/app/views/shared/_broadcast_message.html.haml @@ -3,7 +3,7 @@ %div{ class: "broadcast-message #{'alert-warning' if is_banner} broadcast-#{message.broadcast_type}-message #{opts[:preview] && 'preview'} js-broadcast-notification-#{message.id} gl-display-flex", style: broadcast_message_style(message), dir: 'auto' } .flex-grow-1.text-right.pr-2 - = sprite_icon('bullhorn', size: 16, css_class: 'vertical-align-text-top') + = sprite_icon('bullhorn', css_class: 'vertical-align-text-top') %div{ class: !fluid_layout && 'container-limited' } = render_broadcast_message(message) .flex-grow-1.text-right{ style: 'flex-basis: 0' } diff --git a/app/views/shared/_check_recovery_settings.html.haml b/app/views/shared/_check_recovery_settings.html.haml index e3de34a5ab9..7ac90e5af03 100644 --- a/app/views/shared/_check_recovery_settings.html.haml +++ b/app/views/shared/_check_recovery_settings.html.haml @@ -1,6 +1,6 @@ .gl-alert.gl-alert-warning.js-recovery-settings-callout{ role: 'alert', data: { feature_id: "account_recovery_regular_check", dismiss_endpoint: user_callouts_path, defer_links: "true" } } %button.js-close.gl-alert-dismiss.gl-cursor-pointer{ type: 'button', 'aria-label' => _('Dismiss') } - = sprite_icon('close', size: 16, css_class: 'gl-icon') + = sprite_icon('close', css_class: 'gl-icon') .gl-alert-body - account_link_start = '<a class="deferred-link" href="%{url}">'.html_safe % { url: profile_account_path } = _("Please ensure your account's %{account_link_start}recovery settings%{account_link_end} are up to date.").html_safe % { account_link_start: account_link_start, account_link_end: '</a>'.html_safe } diff --git a/app/views/shared/_issuable_meta_data.html.haml b/app/views/shared/_issuable_meta_data.html.haml index c1749e1f96e..3eb27f002ef 100644 --- a/app/views/shared/_issuable_meta_data.html.haml +++ b/app/views/shared/_issuable_meta_data.html.haml @@ -11,15 +11,15 @@ - if upvotes > 0 %li.issuable-upvotes.d-none.d-sm-block.has-tooltip{ title: _('Upvotes') } - = sprite_icon('thumb-up', size: 16, css_class: "vertical-align-middle") + = sprite_icon('thumb-up', css_class: "vertical-align-middle") = upvotes - if downvotes > 0 %li.issuable-downvotes.d-none.d-sm-block.has-tooltip{ title: _('Downvotes') } - = sprite_icon('thumb-down', size: 16, css_class: "vertical-align-middle") + = sprite_icon('thumb-down', css_class: "vertical-align-middle") = downvotes %li.issuable-comments.d-none.d-sm-block = link_to issuable_path, class: ['has-tooltip', ('no-comments' if note_count == 0)], title: _('Comments') do - = sprite_icon('comments', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom') = note_count diff --git a/app/views/shared/_md_preview.html.haml b/app/views/shared/_md_preview.html.haml index c3818b9f7ae..c7c36d79fa0 100644 --- a/app/views/shared/_md_preview.html.haml +++ b/app/views/shared/_md_preview.html.haml @@ -2,7 +2,7 @@ - if defined?(@merge_request) && @merge_request.discussion_locked? .issuable-note-warning - = sprite_icon('lock', size: 16, css_class: 'icon') + = sprite_icon('lock', css_class: 'icon') %span = _('This merge request is locked.') = _('Only project members can comment.') diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml index 2fc4a1a8bd3..47fb38d979d 100644 --- a/app/views/shared/_new_project_item_select.html.haml +++ b/app/views/shared/_new_project_item_select.html.haml @@ -4,4 +4,4 @@ = loading_icon(color: 'light') = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path], with_shared: local_assigns[:with_shared], include_projects_in_subgroups: local_assigns[:include_projects_in_subgroups] }, with_feature_enabled: local_assigns[:with_feature_enabled] %button.btn.btn-success.new-project-item-select-button.qa-new-project-item-select-button.gl-p-0 - = sprite_icon('chevron-down', size: 16) + = sprite_icon('chevron-down') diff --git a/app/views/shared/_no_ssh.html.haml b/app/views/shared/_no_ssh.html.haml index 2b04e3e1c98..abf39fdc644 100644 --- a/app/views/shared/_no_ssh.html.haml +++ b/app/views/shared/_no_ssh.html.haml @@ -1,8 +1,8 @@ - if show_no_ssh_key_message? %div{ class: 'no-ssh-key-message gl-alert gl-alert-warning', role: 'alert' } - = sprite_icon('warning', size: 16, css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title') + = sprite_icon('warning', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title') %button{ class: 'gl-alert-dismiss hide-no-ssh-message', type: 'button', 'aria-label': _('Dismiss') } - = sprite_icon('close', size: 16, css_class: 'gl-icon s16') + = sprite_icon('close', css_class: 'gl-icon s16') .gl-alert-body = s_("MissingSSHKeyWarningLink|You won't be able to pull or push project code via SSH until you add an SSH key to your profile").html_safe .gl-alert-actions diff --git a/app/views/shared/_outdated_browser.html.haml b/app/views/shared/_outdated_browser.html.haml index 30255e18f04..624cc99440c 100644 --- a/app/views/shared/_outdated_browser.html.haml +++ b/app/views/shared/_outdated_browser.html.haml @@ -1,6 +1,6 @@ - if outdated_browser? .gl-alert.gl-alert-danger.outdated-browser{ :role => "alert" } - = sprite_icon('error', size: 16, css_class: "gl-alert-icon gl-alert-icon-no-title gl-icon") + = sprite_icon('error', css_class: "gl-alert-icon gl-alert-icon-no-title gl-icon") .gl-alert-body - if browser.ie? && browser.version.to_i == 11 - feedback_link_url = 'https://gitlab.com/gitlab-org/gitlab/issues/197987' diff --git a/app/views/shared/_sidebar_toggle_button.html.haml b/app/views/shared/_sidebar_toggle_button.html.haml index 1431966c83d..9d1970093b8 100644 --- a/app/views/shared/_sidebar_toggle_button.html.haml +++ b/app/views/shared/_sidebar_toggle_button.html.haml @@ -4,5 +4,5 @@ %span.collapse-text= _("Collapse sidebar") = button_tag class: 'close-nav-button', type: 'button' do - = sprite_icon('close', size: 16) + = sprite_icon('close') %span.collapse-text= _("Close sidebar") diff --git a/app/views/shared/_zen.html.haml b/app/views/shared/_zen.html.haml index 914409d0e65..d1a15b84c77 100644 --- a/app/views/shared/_zen.html.haml +++ b/app/views/shared/_zen.html.haml @@ -16,4 +16,4 @@ - else = text_area_tag attr, current_text, data: { qa_selector: qa_selector }, class: classes, placeholder: placeholder %a.zen-control.zen-control-leave.js-zen-leave.gl-text-gray-700{ href: "#" } - = sprite_icon('compress', size: 16) + = sprite_icon('compress') diff --git a/app/views/shared/groups/_group.html.haml b/app/views/shared/groups/_group.html.haml index dd36e233fc8..a4ac884a4e9 100644 --- a/app/views/shared/groups/_group.html.haml +++ b/app/views/shared/groups/_group.html.haml @@ -18,11 +18,11 @@ .stats.gl-text-gray-700.gl-flex-shrink-0 %span.gl-ml-5 - = sprite_icon('bookmark', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('bookmark', css_class: 'gl-vertical-align-text-bottom') = number_with_delimiter(group.projects.non_archived.count) %span.gl-ml-5 - = sprite_icon('users', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('users', css_class: 'gl-vertical-align-text-bottom') = number_with_delimiter(group.users.count) %span.gl-ml-5.visibility-icon.has-tooltip{ data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group) } diff --git a/app/views/shared/issuable/_feed_buttons.html.haml b/app/views/shared/issuable/_feed_buttons.html.haml index 790cd5ca1cf..86c2e243718 100644 --- a/app/views/shared/issuable/_feed_buttons.html.haml +++ b/app/views/shared/issuable/_feed_buttons.html.haml @@ -1,4 +1,4 @@ = link_to safe_params.merge(rss_url_options), class: 'btn btn-svg has-tooltip', data: { container: 'body', testid: 'rss-feed-link' }, title: _('Subscribe to RSS feed') do - = sprite_icon('rss', css_class: 'qa-rss-icon', size: 16) + = sprite_icon('rss', css_class: 'qa-rss-icon') = link_to safe_params.merge(calendar_url_options), class: 'btn has-tooltip', data: { container: 'body' }, title: _('Subscribe to calendar') do = sprite_icon('calendar') diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 4cb3e38efe0..6f31d7290b7 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -32,7 +32,7 @@ - milestone = issuable_sidebar[:milestone] || {} .block.milestone{ data: { qa_selector: 'milestone_block' } } .sidebar-collapsed-icon.has-tooltip{ title: sidebar_milestone_tooltip_label(milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } } - = sprite_icon('clock', size: 16) + = sprite_icon('clock') %span.milestone-title.collapse-truncated-title - if milestone.present? = milestone[:title] diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml index 79dc3043e8d..d17fc5e2eef 100644 --- a/app/views/shared/members/_member.html.haml +++ b/app/views/shared/members/_member.html.haml @@ -62,7 +62,7 @@ - if show_controls && member.source == current_resource - if member.can_resend_invite? - = link_to sprite_icon('paper-airplane', size: 16), polymorphic_path([:resend_invite, member]), + = link_to sprite_icon('paper-airplane'), polymorphic_path([:resend_invite, member]), method: :post, class: 'btn btn-default align-self-center mr-sm-2', title: _('Resend invite') diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml index 27cedcae9b6..bdacdb23141 100644 --- a/app/views/shared/milestones/_sidebar.html.haml +++ b/app/views/shared/milestones/_sidebar.html.haml @@ -140,7 +140,7 @@ .block.releases .sidebar-collapsed-icon.has-tooltip{ title: milestone_releases_tooltip_text(milestone), data: { container: 'body', placement: 'left', boundary: 'viewport' } } %strong - = sprite_icon("rocket", size: 16) + = sprite_icon("rocket") %span= total_count .title.hide-collapsed= n_('Release', 'Releases', total_count) .hide-collapsed diff --git a/app/views/shared/notes/_hints.html.haml b/app/views/shared/notes/_hints.html.haml index abd5d8cd9db..51c1ee0c4d1 100644 --- a/app/views/shared/notes/_hints.html.haml +++ b/app/views/shared/notes/_hints.html.haml @@ -12,7 +12,7 @@ %span.uploading-container %span.uploading-progress-container.hide - = sprite_icon('media', size: 16, css_class: 'gl-icon gl-vertical-align-text-bottom') + = sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom') %span.attaching-file-message -# Populated by app/assets/javascripts/dropzone_input.js %span.uploading-progress 0% @@ -20,7 +20,7 @@ %span.uploading-error-container.hide %span.uploading-error-icon - = sprite_icon('media', size: 16, css_class: 'gl-icon gl-vertical-align-text-bottom') + = sprite_icon('media', css_class: 'gl-icon gl-vertical-align-text-bottom') %span.uploading-error-message -# Populated by app/assets/javascripts/dropzone_input.js %button.retry-uploading-link{ type: 'button' }= _("Try again") @@ -28,7 +28,7 @@ %button.attach-new-file.markdown-selector{ type: 'button' }= _("attach a new file") %button.btn.markdown-selector.button-attach-file.btn-link{ type: 'button', tabindex: '-1' } - = sprite_icon('media', size: 16) + = sprite_icon('media') %span.text-attach-file<> = _("Attach a file") diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml index c75176cb623..da665f17975 100644 --- a/app/views/shared/notes/_note.html.haml +++ b/app/views/shared/notes/_note.html.haml @@ -63,8 +63,8 @@ - if note.system .system-note-commit-list-toggler.hide = _("Toggle commit list") - = sprite_icon('chevron-down', size: 16, css_class: 'js-chevron-down gl-ml-1 gl-vertical-align-text-bottom') - = sprite_icon('chevron-up', size: 16, css_class: 'js-chevron-up gl-ml-1 gl-vertical-align-text-bottom gl-display-none') + = sprite_icon('chevron-down', css_class: 'js-chevron-down gl-ml-1 gl-vertical-align-text-bottom') + = sprite_icon('chevron-up', css_class: 'js-chevron-up gl-ml-1 gl-vertical-align-text-bottom gl-display-none') - if note.attachment.url .note-attachment - if note.attachment.image? diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml index f712b139c57..2e98b06ec4a 100644 --- a/app/views/shared/notes/_notes_with_form.html.haml +++ b/app/views/shared/notes/_notes_with_form.html.haml @@ -25,7 +25,7 @@ - elsif discussion_locked .disabled-comment.text-center.gl-mt-3 %span.issuable-note-warning - = sprite_icon('lock', size: 16, css_class: 'icon') + = sprite_icon('lock', css_class: 'icon') %span = html_escape(_("This %{issuable} is locked. Only %{strong_open}project members%{strong_close} can comment.")) % { issuable: issuable.class.to_s.titleize.downcase, strong_open: '<strong>'.html_safe, strong_close: '</strong>'.html_safe } -# haml-lint:disable InlineJavaScript diff --git a/app/views/shared/notifications/_button.html.haml b/app/views/shared/notifications/_button.html.haml index b4a274a3ecf..f2c7ab648c0 100644 --- a/app/views/shared/notifications/_button.html.haml +++ b/app/views/shared/notifications/_button.html.haml @@ -18,7 +18,7 @@ %div{ class: ("btn-group" if notification_setting.custom?) } - if notification_setting.custom? %button.dropdown-new.btn.btn-defaul.btn-icon.gl-button.has-tooltip.notifications-btn.text-left#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => aria_label, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } } - = sprite_icon("notifications", size: 16, css_class: "js-notification-loading") + = sprite_icon("notifications", css_class: "js-notification-loading") = notification_title(notification_setting.level) %button.btn.dropdown-toggle.d-flex{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } = icon('caret-down') @@ -26,7 +26,7 @@ - else %button.dropdown-new.btn.btn-default.btn-icon.gl-button.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => aria_label, data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } .float-left - = sprite_icon("notifications", size: 16, css_class: "js-notification-loading") + = sprite_icon("notifications", css_class: "js-notification-loading") = notification_title(notification_setting.level) .float-right = icon("caret-down") diff --git a/app/views/shared/projects/_search_bar.html.haml b/app/views/shared/projects/_search_bar.html.haml index c1f2eaba284..a745da32110 100644 --- a/app/views/shared/projects/_search_bar.html.haml +++ b/app/views/shared/projects/_search_bar.html.haml @@ -14,7 +14,7 @@ .filtered-search-box-input-container.pl-2 = render 'shared/projects/search_form', admin_view: false, search_form_placeholder: _("Search projects...") %button.btn.btn-secondary{ type: 'submit', form: 'project-filter-form' } - = sprite_icon('search', size: 16, css_class: 'search-icon ') + = sprite_icon('search', css_class: 'search-icon ') .filtered-search-dropdown.flex-row.align-items-center.mb-2.m-sm-0#filtered-search-visibility-dropdown{ class: flex_grow_and_shrink_xs } .filtered-search-dropdown-label.p-0.pl-sm-3.font-weight-bold %span @@ -25,4 +25,3 @@ %span = _("Sort by") = render 'shared/projects/sort_dropdown' - diff --git a/app/views/shared/snippets/_snippet.html.haml b/app/views/shared/snippets/_snippet.html.haml index cf027252524..25e31fd519b 100644 --- a/app/views/shared/snippets/_snippet.html.haml +++ b/app/views/shared/snippets/_snippet.html.haml @@ -11,7 +11,7 @@ %ul.controls %li = link_to gitlab_snippet_path(snippet, anchor: 'notes'), class: ('no-comments' if notes_count == 0) do - = sprite_icon('comments', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('comments', css_class: 'gl-vertical-align-text-bottom') = notes_count %li %span.sr-only diff --git a/app/views/shared/wikis/_sidebar.html.haml b/app/views/shared/wikis/_sidebar.html.haml index cddf19fbc8e..54f285671a1 100644 --- a/app/views/shared/wikis/_sidebar.html.haml +++ b/app/views/shared/wikis/_sidebar.html.haml @@ -2,11 +2,11 @@ .sidebar-container .block.wiki-sidebar-header.gl-mb-3.w-100 %a.gutter-toggle.float-right.d-block.d-sm-block.d-md-none.js-sidebar-wiki-toggle{ href: "#" } - = sprite_icon('chevron-double-lg-right', size: 16, css_class: 'gl-icon') + = sprite_icon('chevron-double-lg-right', css_class: 'gl-icon') - git_access_url = wiki_path(@wiki, action: :git_access) = link_to git_access_url, class: active_nav_link?(path: 'wikis#git_access') ? 'active' : '', data: { qa_selector: 'clone_repository_link' } do - = sprite_icon('download', size: 16, css_class: 'gl-mr-2') + = sprite_icon('download', css_class: 'gl-mr-2') %span= _("Clone repository") .blocks-container diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml index 111f7e169b9..2f44a57c388 100644 --- a/app/views/users/calendar_activities.html.haml +++ b/app/views/users/calendar_activities.html.haml @@ -6,7 +6,7 @@ - @events.sort_by(&:created_at).each do |event| %li %span.light - = sprite_icon('clock', size: 16, css_class: 'gl-vertical-align-text-bottom') + = sprite_icon('clock', css_class: 'gl-vertical-align-text-bottom') = event.created_at.to_time.in_time_zone.strftime('%-I:%M%P') - if event.visible_to_user?(current_user) - if event.push_action? diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 626ddb49024..94482717d0e 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -26,7 +26,7 @@ = icon('exclamation-circle') - if can?(current_user, :read_user_profile, @user) = link_to user_path(@user, rss_url_options), class: link_classes + 'btn btn-svg btn-default has-tooltip', title: s_('UserProfile|Subscribe'), 'aria-label': 'Subscribe' do - = sprite_icon('rss', css_class: 'qa-rss-icon', size: 16) + = sprite_icon('rss', css_class: 'qa-rss-icon') - if current_user && current_user.admin? = link_to [:admin, @user], class: link_classes + 'btn btn-default', title: s_('UserProfile|View user in admin area'), data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do @@ -55,12 +55,12 @@ .cover-desc.cgray.mb-1.mb-sm-2 - unless @user.location.blank? .profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline.mb-1.mb-sm-0 - = sprite_icon('location', size: 16, css_class: 'vertical-align-sub fgray') + = sprite_icon('location', css_class: 'vertical-align-sub fgray') %span.vertical-align-middle = @user.location - unless work_information(@user).blank? .profile-link-holder.middle-dot-divider-sm.d-block.d-sm-inline - = sprite_icon('work', size: 16, css_class: 'vertical-align-middle fgray') + = sprite_icon('work', css_class: 'vertical-align-middle fgray') %span.vertical-align-middle = work_information(@user) .cover-desc.cgray.mb-1.mb-sm-2 @@ -172,4 +172,3 @@ = s_('UserProfile|This user is blocked') - else = s_('UserProfile|This user has a private profile') - diff --git a/changelogs/unreleased/214100-pre-fill-the-email-input-on-sign-in-sign-up-pages.yml b/changelogs/unreleased/214100-pre-fill-the-email-input-on-sign-in-sign-up-pages.yml new file mode 100644 index 00000000000..883b31c364b --- /dev/null +++ b/changelogs/unreleased/214100-pre-fill-the-email-input-on-sign-in-sign-up-pages.yml @@ -0,0 +1,5 @@ +--- +title: Pre-fill the email input on sign-in / sign up pages +merge_request: 33851 +author: +type: changed diff --git a/changelogs/unreleased/219753-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml b/changelogs/unreleased/219753-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml new file mode 100644 index 00000000000..d097fbe17aa --- /dev/null +++ b/changelogs/unreleased/219753-replace-gl-deprecated-button-with-gl-button-in-app-assets-javascri.yml @@ -0,0 +1,5 @@ +--- +title: Migrate maintenance mode settings button +merge_request: 38901 +author: +type: changed diff --git a/changelogs/unreleased/227240-replace-v-popover-with-gl-popover-in-pipeline_url-vue.yml b/changelogs/unreleased/227240-replace-v-popover-with-gl-popover-in-pipeline_url-vue.yml new file mode 100644 index 00000000000..48d9c1dc4f6 --- /dev/null +++ b/changelogs/unreleased/227240-replace-v-popover-with-gl-popover-in-pipeline_url-vue.yml @@ -0,0 +1,5 @@ +--- +title: Replace v-popover directive with GlPopover in ./app/assets/javascripts/pipelines/components/pipelines_list/pipeline_url.vue.vue +merge_request: 38769 +author: Gilang Gumilar +type: changed diff --git a/changelogs/unreleased/graphql-milestones-top-level.yml b/changelogs/unreleased/graphql-milestones-top-level.yml new file mode 100644 index 00000000000..ef06cc70e75 --- /dev/null +++ b/changelogs/unreleased/graphql-milestones-top-level.yml @@ -0,0 +1,5 @@ +--- +title: Add GraphQL query for a single milestone +merge_request: 38682 +author: +type: added diff --git a/changelogs/unreleased/rails-save-bang-10.yml b/changelogs/unreleased/rails-save-bang-10.yml new file mode 100644 index 00000000000..8faf83ea94a --- /dev/null +++ b/changelogs/unreleased/rails-save-bang-10.yml @@ -0,0 +1,5 @@ +--- +title: Refactor spec/features/merge_requests/* to fix Rails/SaveBang Cop +merge_request: 38591 +author: Rajendra Kadam +type: fixed diff --git a/changelogs/unreleased/vij-deprecate-graphql-snippet-blob.yml b/changelogs/unreleased/vij-deprecate-graphql-snippet-blob.yml new file mode 100644 index 00000000000..cf767502b78 --- /dev/null +++ b/changelogs/unreleased/vij-deprecate-graphql-snippet-blob.yml @@ -0,0 +1,5 @@ +--- +title: Deprecate blob field on GraphQL SnippetType +merge_request: 39088 +author: +type: deprecated diff --git a/config/feature_flags/development/dynamic_image_resizing.yml b/config/feature_flags/development/dynamic_image_resizing.yml new file mode 100644 index 00000000000..72547b7736e --- /dev/null +++ b/config/feature_flags/development/dynamic_image_resizing.yml @@ -0,0 +1,7 @@ +--- +name: dynamic_image_resizing +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37342 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233704 +group: group::memory +type: development +default_enabled: false
\ No newline at end of file diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 704f3727434..768ca220bd6 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -8960,6 +8960,11 @@ type MilestoneEdge { node: Milestone } +""" +Identifier of Milestone +""" +scalar MilestoneID + enum MilestoneStateEnum { active closed @@ -11622,6 +11627,16 @@ type Query { metadata: Metadata """ + Find a milestone + """ + milestone( + """ + Find a milestone by its ID + """ + id: MilestoneID! + ): Milestone + + """ Find a namespace """ namespace( @@ -13739,9 +13754,9 @@ type Snippet implements Noteable { author: User """ - Snippet blob + Snippet blob. Deprecated in 13.3: Use `blobs` """ - blob: SnippetBlob! + blob: SnippetBlob! @deprecated(reason: "Use `blobs`. Deprecated in 13.3") """ Snippet blobs diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index 436571c876b..0423acb6d75 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -25147,6 +25147,16 @@ "possibleTypes": null }, { + "kind": "SCALAR", + "name": "MilestoneID", + "description": "Identifier of Milestone", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { "kind": "ENUM", "name": "MilestoneStateEnum", "description": null, @@ -34302,6 +34312,33 @@ "deprecationReason": null }, { + "name": "milestone", + "description": "Find a milestone", + "args": [ + { + "name": "id", + "description": "Find a milestone by its ID", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "MilestoneID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Milestone", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "namespace", "description": "Find a namespace", "args": [ @@ -40450,7 +40487,7 @@ }, { "name": "blob", - "description": "Snippet blob", + "description": "Snippet blob. Deprecated in 13.3: Use `blobs`", "args": [ ], @@ -40463,8 +40500,8 @@ "ofType": null } }, - "isDeprecated": false, - "deprecationReason": null + "isDeprecated": true, + "deprecationReason": "Use `blobs`. Deprecated in 13.3" }, { "name": "blobs", diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index acd8c29301d..f35e6ec3470 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -2030,7 +2030,7 @@ Represents a snippet entry | Name | Type | Description | | --- | ---- | ---------- | | `author` | User | The owner of the snippet | -| `blob` | SnippetBlob! | Snippet blob | +| `blob` **{warning-solid}** | SnippetBlob! | **Deprecated:** Use `blobs`. Deprecated in 13.3 | | `blobs` | SnippetBlob! => Array | Snippet blobs | | `createdAt` | Time! | Timestamp this snippet was created | | `description` | String | Description of the snippet | diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md index d4fe43130c8..063e5f77adc 100644 --- a/doc/user/gitlab_com/index.md +++ b/doc/user/gitlab_com/index.md @@ -29,7 +29,7 @@ gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAA ## Mail configuration GitLab.com sends emails from the `mg.gitlab.com` domain via [Mailgun](https://www.mailgun.com/) and has -its own dedicated IP address (`192.237.158.143`). +its own dedicated IP address (`192.237.158.143`). NOTE: **Note:** The IP address for `mg.gitlab.com` is subject to change at any time. @@ -216,10 +216,6 @@ sentry_dsn = "X" [runners.machine] IdleCount = 50 IdleTime = 3600 - OffPeakPeriods = ["* * * * * sat,sun *"] - OffPeakTimezone = "UTC" - OffPeakIdleCount = 15 - OffPeakIdleTime = 3600 MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused. MachineName = "srm-%s" MachineDriver = "google" @@ -237,6 +233,16 @@ sentry_dsn = "X" "engine-opt=fixed-cidr-v6=fc00::/7", "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600 ] + [[runners.machine.autoscaling]] + Periods = ["* * * * * sat,sun *"] + Timezone = "UTC" + IdleCount = 70 + IdleTime = 3600 + [[runners.machine.autoscaling]] + Periods = ["* 30-59 3 * * * *", "* 0-30 4 * * * *"] + Timezone = "UTC" + IdleCount = 700 + IdleTime = 3600 [runners.cache] Type = "gcs" Shared = true diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md index c3362704eac..a73a896688e 100644 --- a/doc/user/group/epics/manage_epics.md +++ b/doc/user/group/epics/manage_epics.md @@ -273,6 +273,15 @@ The following issue metadata will be copied to the epic: - Group labels that the issue already has. - Parent epic. **(ULTIMATE)** +### Use an epic template for repeating issues + +You can create a spreadsheet template to manage a pattern of consistently repeating issues. + +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> +For an introduction to epic templates, see [GitLab Epics and Epic Template Tip](https://www.youtube.com/watch?v=D74xKFNw8vg). + +For more on epic templates, see [Epic Templates - Repeatable sets of issues](https://about.gitlab.com/handbook/marketing/product-marketing/getting-started/104/). + ## Manage multi-level child epics **(ULTIMATE)** ### Add a child epic to an epic diff --git a/doc/user/packages/maven_repository/index.md b/doc/user/packages/maven_repository/index.md index 4669a998d25..f98a8eb9c6d 100644 --- a/doc/user/packages/maven_repository/index.md +++ b/doc/user/packages/maven_repository/index.md @@ -783,7 +783,7 @@ is updated: ```yaml deploy: - image: maven:3.3.9-jdk-8 + image: maven:3.6-jdk-11 script: - 'mvn deploy -s ci_settings.xml' only: @@ -808,7 +808,7 @@ is updated: ```yaml deploy: - image: gradle:latest + image: gradle:6.5-jdk11 script: - 'gradle publish' only: diff --git a/lib/gitlab/metrics/templates/gauge.metrics-dashboard.yml b/lib/gitlab/metrics/templates/gauge.metrics-dashboard.yml new file mode 100644 index 00000000000..0796329bcb5 --- /dev/null +++ b/lib/gitlab/metrics/templates/gauge.metrics-dashboard.yml @@ -0,0 +1,23 @@ +# Only one dashboard should be defined per file +# More info: https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html +dashboard: 'Guage Panel Example' + +# For more information about the required properties of panel_groups +# please visit: https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html#panel-group-panel_groups-properties +panel_groups: + - group: 'Server Statistics' + panels: + - title: "Memory usage" + # More information about gauge panel types can be found here: + # https://docs.gitlab.com/ee/operations/metrics/dashboards/panel_types.html#gauge + type: "gauge-chart" + min_value: 0 + max_value: 1024 + split: 10 + thresholds: + mode: "percentage" + values: [60, 90] + format: "megabytes" + metrics: + - query: '(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / 1024 / 1024' + unit: 'MB' diff --git a/lib/gitlab/metrics/templates/single-stat.metrics-dashboard.yml b/lib/gitlab/metrics/templates/single-stat.metrics-dashboard.yml new file mode 100644 index 00000000000..18c27fffc7c --- /dev/null +++ b/lib/gitlab/metrics/templates/single-stat.metrics-dashboard.yml @@ -0,0 +1,17 @@ +# Only one dashboard should be defined per file +# More info: https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html +dashboard: 'Heatmap Panel Example' + +# For more information about the required properties of panel_groups +# please visit: https://docs.gitlab.com/ee/operations/metrics/dashboards/yaml.html#panel-group-panel_groups-properties +panel_groups: + - group: 'Server Statistics' + panels: + - title: "Memory usage" + # More information about heatmap panel types can be found here: + # https://docs.gitlab.com/ee/operations/metrics/dashboards/panel_types.html#single-stat + type: "single-stat" + metrics: + - query: '(node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / 1024 / 1024' + unit: 'MB' + label: "Used memory" diff --git a/lib/gitlab/redis/hll.rb b/lib/gitlab/redis/hll.rb index 494736d5d5f..ff5754675e2 100644 --- a/lib/gitlab/redis/hll.rb +++ b/lib/gitlab/redis/hll.rb @@ -3,6 +3,9 @@ module Gitlab module Redis class HLL + KEY_REGEX = %r{\A(\w|-|:)*\{\w*\}(\w|-|:)*\z}.freeze + KeyFormatError = Class.new(StandardError) + def self.count(params) self.new.count(params) end @@ -11,15 +14,25 @@ module Gitlab self.new.add(params) end - # NOTE: It is important to make sure the keys are in the same hash slot - # https://redis.io/topics/cluster-spec#keys-hash-tags def count(keys:) Gitlab::Redis::SharedState.with do |redis| redis.pfcount(*keys) end end + # Check a basic format for the Redis key in order to ensure the keys are in the same hash slot + # + # Examples of keys + # project:{1}:set_a + # project:{1}:set_b + # project:{2}:set_c + # 2020-216-{project_action} + # i_{analytics}_dev_ops_score-2020-32 def add(key:, value:, expiry:) + unless KEY_REGEX.match?(key) + raise KeyFormatError.new("Invalid key format. #{key} key should have changeable parts in curly braces. See https://docs.gitlab.com/ee/development/redis.html#multi-key-commands") + end + Gitlab::Redis::SharedState.with do |redis| redis.multi do |multi| multi.pfadd(key, value) diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 6d935bb8828..e3b1cb3d016 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -156,6 +156,18 @@ module Gitlab ] end + def send_scaled_image(location, width) + params = { + 'Location' => location, + 'Width' => width + } + + [ + SEND_DATA_HEADER, + "send-scaled-img:#{encode(params)}" + ] + end + def channel_websocket(channel) details = { 'Channel' => { diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d739b544fdd..9f74aa27840 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2330,6 +2330,9 @@ msgstr "" msgid "All environments" msgstr "" +msgid "All epics" +msgstr "" + msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings." msgstr "" @@ -5027,6 +5030,9 @@ msgstr "" msgid "Closed %{epicTimeagoDate}" msgstr "" +msgid "Closed epics" +msgstr "" + msgid "Closed issues" msgstr "" @@ -16861,6 +16867,9 @@ msgstr "" msgid "Open comment type dropdown" msgstr "" +msgid "Open epics" +msgstr "" + msgid "Open errors" msgstr "" @@ -22477,7 +22486,7 @@ msgstr "" msgid "SlackIntegration|Select events below to enable notifications. The %{strong_open}Slack channel names%{strong_close} and %{strong_open}Slack username%{strong_close} fields are optional." msgstr "" -msgid "SlackIntegration|This service send notifications about projects' events to Slack channels. To set up this service:" +msgid "SlackIntegration|This service sends notifications about project events to Slack channels. To set up this service:" msgstr "" msgid "SlackService|2. Paste the %{strong_open}Token%{strong_close} into the field below" diff --git a/scripts/regenerate-schema b/scripts/regenerate-schema index cedd612f766..e2d46d14218 100755 --- a/scripts/regenerate-schema +++ b/scripts/regenerate-schema @@ -3,6 +3,7 @@ # frozen_string_literal: true require 'open3' +require 'fileutils' require 'uri' class SchemaRegenerator @@ -19,11 +20,19 @@ class SchemaRegenerator # these to disable/enable migrations. MIGRATION_DIRS = %w[db/migrate db/post_migrate].freeze + ## + # Directory where we store schema versions + # + # The remove_schema_migration_files removes files added in this + # directory when it runs. + SCHEMA_MIGRATIONS_DIR = 'db/schema_migrations/' + def execute Dir.chdir(File.expand_path('..', __dir__)) do checkout_ref checkout_clean_schema hide_migrations + remove_schema_migration_files reset_db unhide_migrations migrate @@ -111,6 +120,35 @@ class SchemaRegenerator end ## + # Remove files added to db/schema_migrations + # + # In order to properly reset the database and re-run migrations + # the schema migrations for new migrations must be removed. + def remove_schema_migration_files + (untracked_schema_migrations + commited_schema_migrations).each do |schema_migration| + FileUtils.rm(schema_migration) + end + end + + ## + # List of untracked schema migrations + # + # Get a list of schema migrations that are not tracked so we can remove them + def untracked_schema_migrations + git_command = "git ls-files --others --exclude-standard -- #{SCHEMA_MIGRATIONS_DIR}" + run(git_command).chomp.split("\n") + end + + ## + # List of untracked schema migrations + # + # Get a list of schema migrations that have been committed since the last + def commited_schema_migrations + git_command = "git diff --name-only --diff-filter=A #{merge_base} -- #{SCHEMA_MIGRATIONS_DIR}" + run(git_command).chomp.split("\n") + end + + ## # Run rake task to reset the database. def reset_db run %q[bin/rails db:reset RAILS_ENV=test] diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb index 7cfaf1b248f..e24e4cbf5e7 100644 --- a/spec/controllers/concerns/send_file_upload_spec.rb +++ b/spec/controllers/concerns/send_file_upload_spec.rb @@ -21,6 +21,12 @@ RSpec.describe SendFileUpload do let(:controller_class) do Class.new do include SendFileUpload + + def params + {} + end + + def current_user; end end end @@ -42,6 +48,89 @@ RSpec.describe SendFileUpload do FileUtils.rm_f(temp_file) end + shared_examples 'handles image resize requests' do + let(:headers) { double } + + before do + allow(uploader).to receive(:image?).and_return(true) + allow(uploader).to receive(:mounted_as).and_return(:avatar) + + allow(controller).to receive(:headers).and_return(headers) + # both of these are valid cases, depending on whether we are dealing with + # local or remote files + allow(controller).to receive(:send_file) + allow(controller).to receive(:redirect_to) + end + + context 'when feature is enabled for current user' do + let(:user) { build(:user) } + + before do + stub_feature_flags(dynamic_image_resizing: user) + allow(controller).to receive(:current_user).and_return(user) + end + + context 'with valid width parameter' do + it 'renders OK with workhorse command header' do + expect(controller).not_to receive(:send_file) + expect(controller).to receive(:params).at_least(:once).and_return(width: '64') + expect(controller).to receive(:head).with(:ok) + expect(headers).to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/) + + subject + end + end + + context 'with missing width parameter' do + it 'does not write workhorse command header' do + expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/) + + subject + end + end + + context 'with invalid width parameter' do + it 'does not write workhorse command header' do + expect(controller).to receive(:params).at_least(:once).and_return(width: 'not a number') + expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/) + + subject + end + end + + context 'with width that is not allowed' do + it 'does not write workhorse command header' do + expect(controller).to receive(:params).at_least(:once).and_return(width: '63') + expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/) + + subject + end + end + + context 'when image file is not an avatar' do + it 'does not write workhorse command header' do + expect(uploader).to receive(:mounted_as).and_return(nil) # FileUploader is not mounted + expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/) + + subject + end + end + end + + context 'when feature is disabled' do + before do + stub_feature_flags(dynamic_image_resizing: false) + end + + it 'does not write workhorse command header' do + expect(controller).to receive(:params).at_least(:once).and_return(width: '64') + expect(headers).not_to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-scaled-img:/) + + subject + end + end + end + context 'when local file is used' do before do uploader.store!(temp_file) @@ -52,6 +141,8 @@ RSpec.describe SendFileUpload do subject end + + it_behaves_like 'handles image resize requests' end context 'with inline image' do @@ -155,6 +246,8 @@ RSpec.describe SendFileUpload do it_behaves_like 'proxied file' end end + + it_behaves_like 'handles image resize requests' end end end diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 60c37d1e125..e66a40720da 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -112,7 +112,7 @@ RSpec.describe 'Commits' do describe 'Cancel build' do it 'cancels build', :js, :sidekiq_might_not_need_inline do visit pipeline_path(pipeline) - find('.js-btn-cancel-pipeline').click + find('[data-testid="cancelPipeline"]').click expect(page).to have_content 'canceled' end end diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb index c0f453206a8..e7bcd7876ea 100644 --- a/spec/features/invites_spec.rb +++ b/spec/features/invites_spec.rb @@ -48,6 +48,14 @@ RSpec.describe 'Invites', :aggregate_failures do expect(page).to have_content('To accept this invitation, sign in') end + it 'pre-fills the "Username or email" field on the sign in box with the invite_email from the invite' do + expect(find_field('Username or email').value).to eq(group_invite.invite_email) + end + + it 'pre-fills the Email field on the sign up box with the invite_email from the invite' do + expect(find_field('Email').value).to eq(group_invite.invite_email) + end + it 'sign in, grants access and redirects to group page' do fill_in_sign_in_form(user) diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb index d5ff31de073..e61ae4ea795 100644 --- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb @@ -154,7 +154,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do context 'view merge request with MWPS enabled but automatically merge fails' do before do - merge_request.update( + merge_request.update!( merge_user: merge_request.author, merge_error: 'Something went wrong.' ) @@ -173,7 +173,7 @@ RSpec.describe 'Merge request > User merges when pipeline succeeds', :js do context 'view merge request with MWPS enabled but automatically merge fails' do before do - merge_request.update( + merge_request.update!( merge_user: merge_request.author, merge_error: 'Something went wrong.' ) diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb index 6ecffb05009..9556142ecb8 100644 --- a/spec/features/merge_request/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb @@ -193,7 +193,7 @@ RSpec.describe 'Merge request > User posts diff notes', :js do context 'when the MR only supports legacy diff notes' do before do - merge_request.merge_request_diff.update(start_commit_sha: nil) + merge_request.merge_request_diff.update!(start_commit_sha: nil) visit diffs_project_merge_request_path(project, merge_request, view: 'inline') end diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb index aa3840b4376..f2adfd21e49 100644 --- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb +++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb @@ -23,7 +23,7 @@ RSpec.describe 'Merge request > User resolves diff notes and threads', :js do before do project.add_maintainer(user) sign_in(user) - note.destroy + note.destroy! visit_merge_request end diff --git a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb index ec2fb856be5..7f4249336fe 100644 --- a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb +++ b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb @@ -26,7 +26,7 @@ RSpec.describe 'Merge request > User cherry-picks', :js do context 'without a merge commit' do before do merge_request.merge_commit_sha = nil - merge_request.save + merge_request.save! end it 'does not show a Cherry-pick button' do diff --git a/spec/features/merge_request/user_sees_discussions_spec.rb b/spec/features/merge_request/user_sees_discussions_spec.rb index ca8c4f84677..74d1b8b628c 100644 --- a/spec/features/merge_request/user_sees_discussions_spec.rb +++ b/spec/features/merge_request/user_sees_discussions_spec.rb @@ -13,8 +13,8 @@ RSpec.describe 'Merge request > User sees threads', :js do end describe "Diff discussions" do - let!(:old_merge_request_diff) { merge_request.merge_request_diffs.create(diff_refs: outdated_diff_refs) } - let!(:new_merge_request_diff) { merge_request.merge_request_diffs.create } + let!(:old_merge_request_diff) { merge_request.merge_request_diffs.create!(diff_refs: outdated_diff_refs) } + let!(:new_merge_request_diff) { merge_request.merge_request_diffs.create! } let!(:outdated_discussion) { create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: outdated_position).to_discussion } let!(:active_discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project).to_discussion } let(:outdated_position) do diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index ce49e9f4141..c7d26dfc814 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -302,7 +302,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'view merge request with MWPS enabled but automatically merge fails' do before do - merge_request.update( + merge_request.update!( auto_merge_enabled: true, auto_merge_strategy: AutoMergeService::STRATEGY_MERGE_WHEN_PIPELINE_SUCCEEDS, merge_user: merge_request.author, @@ -324,7 +324,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'view merge request with MWPS enabled but automatically merge fails' do before do - merge_request.update( + merge_request.update!( merge_when_pipeline_succeeds: true, merge_user: merge_request.author, merge_error: 'Something went wrong' @@ -345,9 +345,9 @@ RSpec.describe 'Merge request > User sees merge widget', :js do context 'view merge request where fast-forward merge is not possible' do before do - project.update(merge_requests_ff_only_enabled: true) + project.update!(merge_requests_ff_only_enabled: true) - merge_request.update( + merge_request.update!( merge_user: merge_request.author, merge_status: :cannot_be_merged ) @@ -380,19 +380,19 @@ RSpec.describe 'Merge request > User sees merge widget', :js do end end - context 'user can merge into source project but cannot push to fork', :js do - let(:fork_project) { create(:project, :public, :repository) } + context 'user can merge into target project but cannot push to fork', :js do + let(:forked_project) { fork_project(project, nil, repository: true) } let(:user2) { create(:user) } before do project.add_maintainer(user2) sign_out(:user) sign_in(user2) - merge_request.update(target_project: fork_project) + merge_request.update!(source_project: forked_project) visit project_merge_request_path(project, merge_request) end - it 'user can merge into the source project' do + it 'user can merge into the target project', :sidekiq_inline do expect(page).to have_button('Merge', disabled: false) end @@ -409,7 +409,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do project.add_developer(user2) sign_out(:user) sign_in(user2) - merge_request.update( + merge_request.update!( source_project: forked_project, target_project: project, merge_params: { 'force_remove_source_branch' => '1' } @@ -879,7 +879,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do let!(:pipeline) { create(:ci_pipeline, status: 'success', sha: sha, project: project, ref: merge_request.source_branch) } before do - project.update( + project.update!( visibility_level: Gitlab::VisibilityLevel::PUBLIC, public_builds: false ) diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb index 75319c8a22d..a89ae5c7464 100644 --- a/spec/features/merge_request/user_sees_versions_spec.rb +++ b/spec/features/merge_request/user_sees_versions_spec.rb @@ -5,14 +5,14 @@ require 'spec_helper' RSpec.describe 'Merge request > User sees versions', :js do let(:merge_request) do create(:merge_request).tap do |mr| - mr.merge_request_diff.destroy + mr.merge_request_diff.destroy! end end let(:project) { merge_request.source_project } let(:user) { project.creator } - let!(:merge_request_diff1) { merge_request.merge_request_diffs.create(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } - let!(:merge_request_diff2) { merge_request.merge_request_diffs.create(head_commit_sha: nil) } - let!(:merge_request_diff3) { merge_request.merge_request_diffs.create(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') } + let!(:merge_request_diff1) { merge_request.merge_request_diffs.create!(head_commit_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } + let!(:merge_request_diff2) { merge_request.merge_request_diffs.create!(head_commit_sha: nil) } + let!(:merge_request_diff3) { merge_request.merge_request_diffs.create!(head_commit_sha: '5937ac0a7beb003549fc5fd26fc247adbce4a52e') } let!(:params) { {} } before do diff --git a/spec/features/merge_requests/user_mass_updates_spec.rb b/spec/features/merge_requests/user_mass_updates_spec.rb index 589825f12af..179bf84a729 100644 --- a/spec/features/merge_requests/user_mass_updates_spec.rb +++ b/spec/features/merge_requests/user_mass_updates_spec.rb @@ -95,7 +95,7 @@ RSpec.describe 'Merge requests > User mass updates', :js do describe 'unset milestone' do before do merge_request.milestone = milestone - merge_request.save + merge_request.save! visit project_merge_requests_path(project) end diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index b3f671d57a9..a05910cd892 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -37,7 +37,7 @@ RSpec.describe 'Environments page', :js do expect(page).to have_css('.environments-container') expect(page.all('.environment-name').length).to eq(1) - expect(page.all('.ic-stop').length).to eq(1) + expect(page.all('[data-testid="stop-icon"]').length).to eq(1) end end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index f0b4d2e88b2..70cc64e9308 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -399,7 +399,7 @@ RSpec.describe 'Pipeline', :js do context 'when retrying' do before do - find('.js-retry-button').click + find('[data-testid="retryButton"]').click end it 'does not show a "Retry" button', :sidekiq_might_not_need_inline do @@ -901,7 +901,7 @@ RSpec.describe 'Pipeline', :js do context 'when retrying' do before do - find('.js-retry-button').click + find('[data-testid="retryButton"]').click end it 'does not show a "Retry" button', :sidekiq_might_not_need_inline do diff --git a/spec/frontend/batch_comments/components/drafts_count_spec.js b/spec/frontend/batch_comments/components/drafts_count_spec.js index 9d9fffce7e7..41583a94fcf 100644 --- a/spec/frontend/batch_comments/components/drafts_count_spec.js +++ b/spec/frontend/batch_comments/components/drafts_count_spec.js @@ -24,7 +24,7 @@ describe('Batch comments drafts count component', () => { }); it('renders count', () => { - expect(vm.$el.querySelector('.drafts-count-number').textContent).toBe('1'); + expect(vm.$el.textContent).toContain('1'); }); it('renders screen reader text', done => { diff --git a/spec/frontend/environments/environment_external_url_spec.js b/spec/frontend/environments/environment_external_url_spec.js index 9997ea94941..4c133665979 100644 --- a/spec/frontend/environments/environment_external_url_spec.js +++ b/spec/frontend/environments/environment_external_url_spec.js @@ -1,4 +1,4 @@ -import { shallowMount } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; import ExternalUrlComp from '~/environments/components/environment_external_url.vue'; describe('External URL Component', () => { @@ -6,7 +6,7 @@ describe('External URL Component', () => { const externalUrl = 'https://gitlab.com'; beforeEach(() => { - wrapper = shallowMount(ExternalUrlComp, { propsData: { externalUrl } }); + wrapper = mount(ExternalUrlComp, { propsData: { externalUrl } }); }); it('should link to the provided externalUrl prop', () => { diff --git a/spec/frontend/environments/environment_stop_spec.js b/spec/frontend/environments/environment_stop_spec.js index f971cf56b65..37d65c9da5a 100644 --- a/spec/frontend/environments/environment_stop_spec.js +++ b/spec/frontend/environments/environment_stop_spec.js @@ -1,7 +1,7 @@ import $ from 'jquery'; import { shallowMount } from '@vue/test-utils'; import StopComponent from '~/environments/components/environment_stop.vue'; -import LoadingButton from '~/vue_shared/components/loading_button.vue'; +import { GlButton } from '@gitlab/ui'; import eventHub from '~/environments/event_hub'; $.fn.tooltip = () => {}; @@ -17,7 +17,7 @@ describe('Stop Component', () => { }); }; - const findButton = () => wrapper.find(LoadingButton); + const findButton = () => wrapper.find(GlButton); beforeEach(() => { jest.spyOn(window, 'confirm'); diff --git a/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js b/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js index c0851096d8e..158f70f7d47 100644 --- a/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js +++ b/spec/frontend/filtered_search/components/recent_searches_dropdown_content_spec.js @@ -57,7 +57,11 @@ describe('Recent Searches Dropdown Content', () => { beforeEach(() => { createComponent({ - items: ['foo', 'author:@root label:~foo bar'], + items: [ + 'foo', + 'author:@root label:~foo bar', + [{ type: 'author_username', value: { data: 'toby', operator: '=' } }], + ], isLocalStorageAvailable: true, }); }); @@ -76,7 +80,7 @@ describe('Recent Searches Dropdown Content', () => { }); it('renders a correct amount of dropdown items', () => { - expect(findDropdownItems()).toHaveLength(2); + expect(findDropdownItems()).toHaveLength(2); // Ignore non-string recent item }); it('expect second dropdown to have 2 tokens', () => { diff --git a/spec/frontend/maintenance_mode_settings/components/app_spec.js b/spec/frontend/maintenance_mode_settings/components/app_spec.js index 0453354b008..a67bc63cfe1 100644 --- a/spec/frontend/maintenance_mode_settings/components/app_spec.js +++ b/spec/frontend/maintenance_mode_settings/components/app_spec.js @@ -1,6 +1,6 @@ import { shallowMount } from '@vue/test-utils'; import MaintenanceModeSettingsApp from '~/maintenance_mode_settings/components/app.vue'; -import { GlToggle, GlFormTextarea, GlDeprecatedButton } from '@gitlab/ui'; +import { GlToggle, GlFormTextarea, GlButton } from '@gitlab/ui'; describe('MaintenanceModeSettingsApp', () => { let wrapper; @@ -16,7 +16,7 @@ describe('MaintenanceModeSettingsApp', () => { const findMaintenanceModeSettingsContainer = () => wrapper.find('article'); const findGlToggle = () => wrapper.find(GlToggle); const findGlFormTextarea = () => wrapper.find(GlFormTextarea); - const findGlButton = () => wrapper.find(GlDeprecatedButton); + const findGlButton = () => wrapper.find(GlButton); describe('template', () => { beforeEach(() => { @@ -35,7 +35,7 @@ describe('MaintenanceModeSettingsApp', () => { expect(findGlFormTextarea().exists()).toBe(true); }); - it('renders the GlDeprecatedButton', () => { + it('renders the GlButton', () => { expect(findGlButton().exists()).toBe(true); }); }); diff --git a/spec/frontend/pipelines/header_component_spec.js b/spec/frontend/pipelines/header_component_spec.js index 1c3a6c545a0..7f7b1f00dab 100644 --- a/spec/frontend/pipelines/header_component_spec.js +++ b/spec/frontend/pipelines/header_component_spec.js @@ -85,13 +85,13 @@ describe('Pipeline details header', () => { }); it('should call postAction when retry button action is clicked', () => { - wrapper.find('.js-retry-button').vm.$emit('click'); + wrapper.find('[data-testid="retryButton"]').vm.$emit('click'); expect(eventHub.$emit).toHaveBeenCalledWith('headerPostAction', 'retry'); }); it('should call postAction when cancel button action is clicked', () => { - wrapper.find('.js-btn-cancel-pipeline').vm.$emit('click'); + wrapper.find('[data-testid="cancelPipeline"]').vm.$emit('click'); expect(eventHub.$emit).toHaveBeenCalledWith('headerPostAction', 'cancel'); }); diff --git a/spec/frontend/releases/util_spec.js b/spec/frontend/releases/util_spec.js index 921da34d62a..90aa9c4c7d8 100644 --- a/spec/frontend/releases/util_spec.js +++ b/spec/frontend/releases/util_spec.js @@ -41,6 +41,24 @@ describe('releases/util.js', () => { }); }); + describe('release.name', () => { + it.each` + input | output + ${null} | ${null} + ${''} | ${null} + ${' \t\n\r\n'} | ${null} + ${' Release name '} | ${'Release name'} + `('converts a name like `$input` to `$output`', ({ input, output }) => { + const release = { name: input }; + + const expectedJson = { + name: output, + }; + + expect(releaseToApiJson(release)).toMatchObject(expectedJson); + }); + }); + describe('when release.milestones is falsy', () => { it('includes a "milestone" property in the returned result as an empty array', () => { const release = {}; diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js index 2e4fb987306..5f474193495 100644 --- a/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js +++ b/spec/frontend/vue_shared/components/filtered_search_bar/filtered_search_bar_root_spec.js @@ -20,7 +20,7 @@ const createComponent = ({ namespace = 'gitlab-org/gitlab-test', recentSearchesStorageKey = 'requirements', tokens = mockAvailableTokens, - sortOptions = mockSortOptions, + sortOptions, searchInputPlaceholder = 'Filter requirements', } = {}) => { const mountMethod = shallow ? shallowMount : mount; @@ -40,7 +40,7 @@ describe('FilteredSearchBarRoot', () => { let wrapper; beforeEach(() => { - wrapper = createComponent(); + wrapper = createComponent({ sortOptions: mockSortOptions }); }); afterEach(() => { @@ -48,10 +48,25 @@ describe('FilteredSearchBarRoot', () => { }); describe('data', () => { - it('initializes `filterValue`, `selectedSortOption` and `selectedSortDirection` data props', () => { + it('initializes `filterValue`, `selectedSortOption` and `selectedSortDirection` data props and displays the sort dropdown', () => { expect(wrapper.vm.filterValue).toEqual([]); expect(wrapper.vm.selectedSortOption).toBe(mockSortOptions[0].sortDirection.descending); expect(wrapper.vm.selectedSortDirection).toBe(SortDirection.descending); + expect(wrapper.contains(GlButtonGroup)).toBe(true); + expect(wrapper.contains(GlButton)).toBe(true); + expect(wrapper.contains(GlDropdown)).toBe(true); + expect(wrapper.contains(GlDropdownItem)).toBe(true); + }); + + it('does not initialize `selectedSortOption` and `selectedSortDirection` when `sortOptions` is not applied and hides the sort dropdown', () => { + const wrapperNoSort = createComponent(); + + expect(wrapperNoSort.vm.filterValue).toEqual([]); + expect(wrapperNoSort.vm.selectedSortOption).toBe(undefined); + expect(wrapperNoSort.contains(GlButtonGroup)).toBe(false); + expect(wrapperNoSort.contains(GlButton)).toBe(false); + expect(wrapperNoSort.contains(GlDropdown)).toBe(false); + expect(wrapperNoSort.contains(GlDropdownItem)).toBe(false); }); }); @@ -103,6 +118,19 @@ describe('FilteredSearchBarRoot', () => { expect(wrapper.vm.sortDirectionTooltip).toBe('Sort direction: Descending'); }); }); + + describe('filteredRecentSearches', () => { + it('returns array of recent searches filtering out any string type (unsupported) items', async () => { + wrapper.setData({ + recentSearches: [{ foo: 'bar' }, 'foo'], + }); + + await wrapper.vm.$nextTick(); + + expect(wrapper.vm.filteredRecentSearches).toHaveLength(1); + expect(wrapper.vm.filteredRecentSearches[0]).toEqual({ foo: 'bar' }); + }); + }); }); describe('watchers', () => { @@ -273,7 +301,7 @@ describe('FilteredSearchBarRoot', () => { }); it('renders search history items dropdown with formatting done using token symbols', async () => { - const wrapperFullMount = createComponent({ shallow: false }); + const wrapperFullMount = createComponent({ sortOptions: mockSortOptions, shallow: false }); wrapperFullMount.vm.recentSearchesStore.addRecentSearch(mockHistoryItems[0]); await wrapperFullMount.vm.$nextTick(); diff --git a/spec/frontend/vue_shared/components/header_ci_component_spec.js b/spec/frontend/vue_shared/components/header_ci_component_spec.js index 216563165d6..5233a64ce5e 100644 --- a/spec/frontend/vue_shared/components/header_ci_component_spec.js +++ b/spec/frontend/vue_shared/components/header_ci_component_spec.js @@ -35,7 +35,7 @@ describe('Header CI Component', () => { vm.$destroy(); }); - const findActionButtons = () => vm.$el.querySelector('.header-action-buttons'); + const findActionButtons = () => vm.$el.querySelector('[data-testid="headerButtons"]'); describe('render', () => { beforeEach(() => { diff --git a/spec/graphql/resolvers/group_milestone_resolver_spec.rb b/spec/graphql/resolvers/group_milestones_resolver_spec.rb index 7504324f8bc..05d0ec38192 100644 --- a/spec/graphql/resolvers/group_milestone_resolver_spec.rb +++ b/spec/graphql/resolvers/group_milestones_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::GroupMilestoneResolver do +RSpec.describe Resolvers::GroupMilestonesResolver do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/resolvers/project_milestone_resolver_spec.rb b/spec/graphql/resolvers/project_milestones_resolver_spec.rb index 36ced72934f..e0b250cfe7c 100644 --- a/spec/graphql/resolvers/project_milestone_resolver_spec.rb +++ b/spec/graphql/resolvers/project_milestones_resolver_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Resolvers::ProjectMilestoneResolver do +RSpec.describe Resolvers::ProjectMilestonesResolver do include GraphqlHelpers describe '#resolve' do diff --git a/spec/graphql/types/query_type_spec.rb b/spec/graphql/types/query_type_spec.rb index 081f99a8307..ab13162b406 100644 --- a/spec/graphql/types/query_type_spec.rb +++ b/spec/graphql/types/query_type_spec.rb @@ -17,6 +17,7 @@ RSpec.describe GitlabSchema.types['Query'] do current_user snippets design_management + milestone user users ] diff --git a/spec/helpers/wiki_helper_spec.rb b/spec/helpers/wiki_helper_spec.rb index 040368b5ebd..6c7172e6232 100644 --- a/spec/helpers/wiki_helper_spec.rb +++ b/spec/helpers/wiki_helper_spec.rb @@ -62,7 +62,7 @@ RSpec.describe WikiHelper do path = "/#{wiki.project.full_path}/-/wikis/pages?direction=#{direction}&sort=#{sort}" helper.link_to(path, type: 'button', class: classes, title: 'Sort direction') do - helper.sprite_icon("sort-#{icon_class}", size: 16) + helper.sprite_icon("sort-#{icon_class}") end end diff --git a/spec/lib/gitlab/redis/hll_spec.rb b/spec/lib/gitlab/redis/hll_spec.rb new file mode 100644 index 00000000000..51768dd81c1 --- /dev/null +++ b/spec/lib/gitlab/redis/hll_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Redis::HLL, :clean_gitlab_redis_shared_state do + describe '.add' do + it 'raise an error when using an invalid key format' do + expect { described_class.add(key: 'test', value: 1, expiry: 1.day) }.to raise_error(Gitlab::Redis::HLL::KeyFormatError) + expect { described_class.add(key: 'test-{metric', value: 1, expiry: 1.day) }.to raise_error(Gitlab::Redis::HLL::KeyFormatError) + expect { described_class.add(key: 'test-{metric}}', value: 1, expiry: 1.day) }.to raise_error(Gitlab::Redis::HLL::KeyFormatError) + end + + it "doesn't raise error when having correct format" do + expect { described_class.add(key: 'test-{metric}', value: 1, expiry: 1.day) }.not_to raise_error + expect { described_class.add(key: 'test-{metric}-1', value: 1, expiry: 1.day) }.not_to raise_error + expect { described_class.add(key: 'test:{metric}-1', value: 1, expiry: 1.day) }.not_to raise_error + expect { described_class.add(key: '2020-216-{project_action}', value: 1, expiry: 1.day) }.not_to raise_error + expect { described_class.add(key: 'i_{analytics}_dev_ops_score-2020-32', value: 1, expiry: 1.day) }.not_to raise_error + end + end +end diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb index 5cb08ac1e76..da327ce7706 100644 --- a/spec/lib/gitlab/workhorse_spec.rb +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -421,6 +421,24 @@ RSpec.describe Gitlab::Workhorse do end end + describe '.send_scaled_image' do + let(:location) { 'http://example.com/avatar.png' } + let(:width) { '150' } + + subject { described_class.send_scaled_image(location, width) } + + it 'sets the header correctly' do + key, command, params = decode_workhorse_header(subject) + + expect(key).to eq("Gitlab-Workhorse-Send-Data") + expect(command).to eq("send-scaled-img") + expect(params).to eq({ + 'Location' => location, + 'Width' => width + }.deep_stringify_keys) + end + end + describe '.send_git_snapshot' do let(:url) { 'http://example.com' } diff --git a/spec/requests/api/graphql/milestone_spec.rb b/spec/requests/api/graphql/milestone_spec.rb new file mode 100644 index 00000000000..59de116fa2b --- /dev/null +++ b/spec/requests/api/graphql/milestone_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Querying a Milestone' do + include GraphqlHelpers + + let_it_be(:current_user) { create(:user) } + let_it_be(:project) { create(:project) } + let_it_be(:milestone) { create(:milestone, project: project) } + + let(:query) do + graphql_query_for('milestone', { id: milestone.to_global_id.to_s }, 'title') + end + + subject { graphql_data['milestone'] } + + before do + post_graphql(query, current_user: current_user) + end + + context 'when the user has access to the milestone' do + before_all do + project.add_guest(current_user) + end + + it_behaves_like 'a working graphql query' + + it { is_expected.to include('title' => milestone.name) } + end + + context 'when the user does not have access to the milestone' do + it_behaves_like 'a working graphql query' + + it { is_expected.to be_nil } + end + + context 'when ID argument is missing' do + let(:query) do + graphql_query_for('milestone', {}, 'title') + end + + it 'raises an exception' do + expect(graphql_errors).to include(a_hash_including('message' => "Field 'milestone' is missing required arguments: id")) + end + end +end |