diff options
Diffstat (limited to 'app')
27 files changed, 239 insertions, 22 deletions
diff --git a/app/assets/javascripts/artifacts/components/artifacts_table_row_details.vue b/app/assets/javascripts/artifacts/components/artifacts_table_row_details.vue index 4a826d0d462..b9aae4bf4e5 100644 --- a/app/assets/javascripts/artifacts/components/artifacts_table_row_details.vue +++ b/app/assets/javascripts/artifacts/components/artifacts_table_row_details.vue @@ -1,5 +1,5 @@ <script> -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scroller'; import getJobArtifactsQuery from '../graphql/queries/get_job_artifacts.query.graphql'; import destroyArtifactMutation from '../graphql/mutations/destroy_artifact.mutation.graphql'; diff --git a/app/assets/javascripts/artifacts/components/job_artifacts_table.vue b/app/assets/javascripts/artifacts/components/job_artifacts_table.vue index 5743ff3ec9e..a7331cc1fd3 100644 --- a/app/assets/javascripts/artifacts/components/job_artifacts_table.vue +++ b/app/assets/javascripts/artifacts/components/job_artifacts_table.vue @@ -9,7 +9,7 @@ import { GlIcon, GlPagination, } from '@gitlab/ui'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; import CiIcon from '~/vue_shared/components/ci_icon.vue'; diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue index b02c3cd2cba..61c0ddef639 100644 --- a/app/assets/javascripts/error_tracking/components/error_details.vue +++ b/app/assets/javascripts/error_tracking/components/error_details.vue @@ -13,7 +13,7 @@ import { GlIcon, } from '@gitlab/ui'; import { mapActions, mapGetters, mapState } from 'vuex'; -import { createAlert, VARIANT_WARNING } from '~/flash'; +import { createAlert, VARIANT_WARNING } from '~/alert'; import { __, sprintf, n__ } from '~/locale'; import Tracking from '~/tracking'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; diff --git a/app/assets/javascripts/error_tracking/store/actions.js b/app/assets/javascripts/error_tracking/store/actions.js index 603f8611005..adbce7750fa 100644 --- a/app/assets/javascripts/error_tracking/store/actions.js +++ b/app/assets/javascripts/error_tracking/store/actions.js @@ -1,4 +1,4 @@ -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { visitUrl } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; import service from '../services'; diff --git a/app/assets/javascripts/error_tracking/store/details/actions.js b/app/assets/javascripts/error_tracking/store/details/actions.js index 1409399940a..89b9432c377 100644 --- a/app/assets/javascripts/error_tracking/store/details/actions.js +++ b/app/assets/javascripts/error_tracking/store/details/actions.js @@ -1,4 +1,4 @@ -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import Poll from '~/lib/utils/poll'; import { __ } from '~/locale'; import service from '../../services'; diff --git a/app/assets/javascripts/error_tracking/store/list/actions.js b/app/assets/javascripts/error_tracking/store/list/actions.js index f633711add3..84e4463ca21 100644 --- a/app/assets/javascripts/error_tracking/store/list/actions.js +++ b/app/assets/javascripts/error_tracking/store/list/actions.js @@ -1,4 +1,4 @@ -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import Poll from '~/lib/utils/poll'; import { __ } from '~/locale'; import Service from '../../services'; diff --git a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue index ce5f7915dbf..57727cb945e 100644 --- a/app/assets/javascripts/feature_flags/components/environments_dropdown.vue +++ b/app/assets/javascripts/feature_flags/components/environments_dropdown.vue @@ -1,7 +1,7 @@ <script> import { GlButton, GlSearchBoxByType } from '@gitlab/ui'; import { debounce } from 'lodash'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/feature_flags/store/edit/actions.js b/app/assets/javascripts/feature_flags/store/edit/actions.js index 97c22781ac5..585bb1be0c4 100644 --- a/app/assets/javascripts/feature_flags/store/edit/actions.js +++ b/app/assets/javascripts/feature_flags/store/edit/actions.js @@ -1,4 +1,4 @@ -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { visitUrl } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/incidents_settings/incidents_settings_service.js b/app/assets/javascripts/incidents_settings/incidents_settings_service.js index d3850114350..195544c746e 100644 --- a/app/assets/javascripts/incidents_settings/incidents_settings_service.js +++ b/app/assets/javascripts/incidents_settings/incidents_settings_service.js @@ -1,4 +1,4 @@ -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { refreshCurrentPage } from '~/lib/utils/url_utility'; import { ERROR_MSG } from './constants'; diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue index 9f200856db3..515d9efaefd 100644 --- a/app/assets/javascripts/releases/components/app_index.vue +++ b/app/assets/javascripts/releases/components/app_index.vue @@ -1,6 +1,6 @@ <script> import { GlButton } from '@gitlab/ui'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { historyPushState } from '~/lib/utils/common_utils'; import { scrollUp } from '~/lib/utils/scroll_utils'; import { setUrlParams, getParameterByName } from '~/lib/utils/url_utility'; diff --git a/app/assets/javascripts/releases/components/app_show.vue b/app/assets/javascripts/releases/components/app_show.vue index 544f2de5132..111d9e232c5 100644 --- a/app/assets/javascripts/releases/components/app_show.vue +++ b/app/assets/javascripts/releases/components/app_show.vue @@ -1,5 +1,5 @@ <script> -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { s__ } from '~/locale'; import { popCreateReleaseNotification } from '~/releases/release_notification_service'; import oneReleaseQuery from '../graphql/queries/one_release.query.graphql'; diff --git a/app/assets/javascripts/releases/release_notification_service.js b/app/assets/javascripts/releases/release_notification_service.js index a4f926d7561..775c62802d4 100644 --- a/app/assets/javascripts/releases/release_notification_service.js +++ b/app/assets/javascripts/releases/release_notification_service.js @@ -1,5 +1,5 @@ import { s__, sprintf } from '~/locale'; -import { createAlert, VARIANT_SUCCESS } from '~/flash'; +import { createAlert, VARIANT_SUCCESS } from '~/alert'; const createReleaseSessionKey = (projectPath) => `createRelease:${projectPath}`; diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js index 42ceed81c00..a7d8825ed33 100644 --- a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js +++ b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js @@ -1,5 +1,5 @@ import { getTag } from '~/rest_api'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { redirectTo } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import createReleaseMutation from '~/releases/graphql/mutations/create_release.mutation.graphql'; diff --git a/app/assets/javascripts/repository/commits_service.js b/app/assets/javascripts/repository/commits_service.js index d029f8cf89f..e26036b5620 100644 --- a/app/assets/javascripts/repository/commits_service.js +++ b/app/assets/javascripts/repository/commits_service.js @@ -1,7 +1,7 @@ import axios from '~/lib/utils/axios_utils'; import { joinPaths } from '~/lib/utils/url_utility'; import { normalizeData } from 'ee_else_ce/repository/utils/commit'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { COMMIT_BATCH_SIZE, I18N_COMMIT_DATA_FETCH_ERROR } from './constants'; let requestedOffsets = []; diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue index 101625a4b72..236351005e7 100644 --- a/app/assets/javascripts/repository/components/blob_content_viewer.vue +++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue @@ -4,7 +4,7 @@ import { uniqueId } from 'lodash'; import BlobContent from '~/blob/components/blob_content.vue'; import BlobHeader from '~/blob/components/blob_header.vue'; import { SIMPLE_BLOB_VIEWER, RICH_BLOB_VIEWER } from '~/blob/components/constants'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { isLoggedIn, handleLocationHash } from '~/lib/utils/common_utils'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/repository/components/blob_controls.vue b/app/assets/javascripts/repository/components/blob_controls.vue index 29c2c3762fc..d3e306619bf 100644 --- a/app/assets/javascripts/repository/components/blob_controls.vue +++ b/app/assets/javascripts/repository/components/blob_controls.vue @@ -1,7 +1,7 @@ <script> import { GlButton } from '@gitlab/ui'; import { __ } from '~/locale'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import getRefMixin from '~/repository/mixins/get_ref'; import initSourcegraph from '~/sourcegraph'; import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob'; diff --git a/app/assets/javascripts/repository/components/fork_info.vue b/app/assets/javascripts/repository/components/fork_info.vue index 9804837b200..51a83e5df8a 100644 --- a/app/assets/javascripts/repository/components/fork_info.vue +++ b/app/assets/javascripts/repository/components/fork_info.vue @@ -1,7 +1,7 @@ <script> import { GlIcon, GlLink, GlSkeletonLoader, GlSprintf } from '@gitlab/ui'; import { s__, sprintf, n__ } from '~/locale'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import forkDetailsQuery from '../queries/fork_details.query.graphql'; export const i18n = { diff --git a/app/assets/javascripts/repository/components/new_directory_modal.vue b/app/assets/javascripts/repository/components/new_directory_modal.vue index b28ebe7bb1e..d9f3a30d28f 100644 --- a/app/assets/javascripts/repository/components/new_directory_modal.vue +++ b/app/assets/javascripts/repository/components/new_directory_modal.vue @@ -8,7 +8,7 @@ import { GlFormTextarea, GlToggle, } from '@gitlab/ui'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { visitUrl } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue index f6d6004ba96..d597a3a78d1 100644 --- a/app/assets/javascripts/repository/components/tree_content.vue +++ b/app/assets/javascripts/repository/components/tree_content.vue @@ -1,6 +1,6 @@ <script> import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { TREE_PAGE_SIZE, diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue index 4603ea2710d..f76242f3d37 100644 --- a/app/assets/javascripts/repository/components/upload_blob_modal.vue +++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue @@ -9,7 +9,7 @@ import { GlButton, GlAlert, } from '@gitlab/ui'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import axios from '~/lib/utils/axios_utils'; import { ContentTypeMultipartFormData } from '~/lib/utils/headers'; import { numberToHumanSize } from '~/lib/utils/number_utils'; diff --git a/app/assets/javascripts/saved_replies/components/list_item.vue b/app/assets/javascripts/saved_replies/components/list_item.vue index dfa9a405dee..774ac745925 100644 --- a/app/assets/javascripts/saved_replies/components/list_item.vue +++ b/app/assets/javascripts/saved_replies/components/list_item.vue @@ -1,11 +1,49 @@ <script> +import { uniqueId } from 'lodash'; +import { GlButton, GlModal, GlModalDirective, GlSprintf, GlTooltipDirective } from '@gitlab/ui'; +import { __ } from '~/locale'; +import deleteSavedReplyMutation from '../queries/delete_saved_reply.mutation.graphql'; + export default { + components: { + GlButton, + GlModal, + GlSprintf, + }, + directives: { + GlModal: GlModalDirective, + GlTooltip: GlTooltipDirective, + }, props: { reply: { type: Object, required: true, }, }, + data() { + return { + isDeleting: false, + modalId: uniqueId('delete-saved-reply-'), + }; + }, + methods: { + onDelete() { + this.isDeleting = true; + + this.$apollo.mutate({ + mutation: deleteSavedReplyMutation, + variables: { + id: this.reply.id, + }, + update: (cache) => { + const cacheId = cache.identify(this.reply); + cache.evict({ id: cacheId }); + }, + }); + }, + }, + actionPrimary: { text: __('Delete'), attributes: { variant: 'danger' } }, + actionSecondary: { text: __('Cancel'), attributes: { variant: 'default' } }, }; </script> @@ -13,7 +51,36 @@ export default { <li class="gl-mb-5"> <div class="gl-display-flex gl-align-items-center"> <strong>{{ reply.name }}</strong> + <div class="gl-ml-auto"> + <gl-button + v-gl-modal="modalId" + v-gl-tooltip + icon="remove" + :aria-label="__('Delete')" + :title="__('Delete')" + variant="danger" + category="secondary" + data-testid="saved-reply-delete-btn" + :loading="isDeleting" + /> + </div> </div> <div class="gl-mt-3 gl-font-monospace">{{ reply.content }}</div> + <gl-modal + :title="__('Delete saved reply')" + :action-primary="$options.actionPrimary" + :action-secondary="$options.actionSecondary" + :modal-id="modalId" + size="sm" + @primary="onDelete" + > + <gl-sprintf + :message="__('Are you sure you want to delete %{name}? This action cannot be undone.')" + > + <template #name + ><strong>{{ reply.name }}</strong></template + > + </gl-sprintf> + </gl-modal> </li> </template> diff --git a/app/assets/javascripts/saved_replies/queries/delete_saved_reply.mutation.graphql b/app/assets/javascripts/saved_replies/queries/delete_saved_reply.mutation.graphql new file mode 100644 index 00000000000..76571ba628c --- /dev/null +++ b/app/assets/javascripts/saved_replies/queries/delete_saved_reply.mutation.graphql @@ -0,0 +1,5 @@ +mutation deleteSavedReply($id: UsersSavedReplyID!) { + savedReplyDestroy(input: { id: $id }) { + errors + } +} diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 58f40e10fd4..e4354eaa452 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -72,7 +72,19 @@ class UsersController < ApplicationController format.json do load_events - pager_json("events/_events", @events.count, events: @events) + + if Feature.enabled?(:profile_tabs_vue, current_user) + @events = if user.include_private_contributions? + @events + else + @events.select { |event| event.visible_to_user?(current_user) } + end + + render json: ::Profile::EventSerializer.new(current_user: current_user, target_user: user) + .represent(@events) + else + pager_json("events/_events", @events.count, events: @events) + end end end end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 590659be0cb..70b40221c35 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -2,6 +2,7 @@ module MergeRequestsHelper include Gitlab::Utils::StrongMemoize + include CompareHelper def create_mr_button_from_event?(event) create_mr_button?(from: event.branch_name, source_project: event.project) diff --git a/app/presenters/event_presenter.rb b/app/presenters/event_presenter.rb index 2f2fb1aa3ba..a098db7fbbc 100644 --- a/app/presenters/event_presenter.rb +++ b/app/presenters/event_presenter.rb @@ -9,7 +9,7 @@ class EventPresenter < Gitlab::View::Presenter::Delegated @visible_to_user_cache = ActiveSupport::Cache::MemoryStore.new end - # Caching `visible_to_user?` method in the presenter beause it might be called multiple times. + # Caching `visible_to_user?` method in the presenter because it might be called multiple times. delegator_override :visible_to_user? def visible_to_user?(user = nil) @visible_to_user_cache.fetch(user&.id) { super(user) } diff --git a/app/serializers/profile/event_entity.rb b/app/serializers/profile/event_entity.rb new file mode 100644 index 00000000000..fe90265c888 --- /dev/null +++ b/app/serializers/profile/event_entity.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +module Profile + class EventEntity < Grape::Entity + include ActionView::Helpers::SanitizeHelper + include RequestAwareEntity + include MarkupHelper + include MergeRequestsHelper + include EventsHelper + + expose :created_at, if: ->(event) { include_private_event?(event) } + expose(:action, if: ->(event) { include_private_event?(event) }) { |event| event_action(event) } + + expose :ref, if: ->(event) { event.visible_to_user?(current_user) && event.push_action? } do + expose(:type) { |event| event.ref_type } # rubocop:disable Style/SymbolProc + expose(:count) { |event| event.ref_count } # rubocop:disable Style/SymbolProc + expose(:name) { |event| event.ref_name } # rubocop:disable Style/SymbolProc + expose(:path) { |event| ref_path(event) } + end + + expose :commit, if: ->(event) { event.visible_to_user?(current_user) && event.push_action? } do + expose(:truncated_sha) { |event| Commit.truncate_sha(event.commit_id) } + expose(:path) { |event| project_commit_path(event.project, event.commit_id) } + expose(:title) { |event| event_commit_title(event.commit_title) } + expose(:count) { |event| event.commits_count } # rubocop:disable Style/SymbolProc + expose(:create_mr_path) { |event| commit_create_mr_path(event) } + expose(:from_truncated_sha) { |event| commit_from(event) if event.commit_from } + expose(:to_truncated_sha) { |event| Commit.truncate_sha(event.commit_to) if event.commit_to } + + expose :compare_path, if: ->(event) { event.push_with_commits? && event.commits_count > 1 } do |event| + project = event.project + from = event.md_ref? ? event.commit_from : project.default_branch + project_compare_path(project, from: from, to: event.commit_to) + end + end + + expose :author, if: ->(event) { include_private_event?(event) } do + expose(:id) { |event| event.author.id } + expose(:name) { |event| event.author.name } + expose(:path) { |event| event.author.username } + end + + expose :target, if: ->(event) { event.visible_to_user?(current_user) } do + expose :target_type + + expose(:title) { |event| event.target_title } # rubocop:disable Style/SymbolProc + expose :target_url, if: ->(event) { event.target } do |event| + Gitlab::UrlBuilder.build(event.target, only_path: true) + end + expose :reference_link_text, if: ->(event) { event.target&.respond_to?(:reference_link_text) } do |event| + event.target.reference_link_text + end + expose :first_line_in_markdown, if: ->(event) { event.note? && event.target && event.project } do |event| + first_line_in_markdown(event.target, :note, 150, project: event.project) + end + expose :attachment, if: ->(event) { event.note? && event.target&.attachment } do + expose(:url) { |event| event.target.attachment.url } + end + end + + expose :resource_parent, if: ->(event) { event.visible_to_user?(current_user) } do + expose(:type) { |event| resource_parent_type(event) } + expose(:full_name) { |event| event.resource_parent&.full_name } + expose(:full_path) { |event| event.resource_parent&.full_path } + end + + private + + def current_user + request.current_user + end + + def target_user + request.target_user + end + + def include_private_event?(event) + event.visible_to_user?(current_user) || target_user.include_private_contributions? + end + + def commit_from(event) + if event.md_ref? + Commit.truncate_sha(event.commit_from) + else + event.project.default_branch + end + end + + def event_action(event) + if event.visible_to_user?(current_user) + event.action + elsif target_user.include_private_contributions? + 'private' + end + end + + def ref_path(event) + project = event.project + commits_link = project_commits_path(project, event.ref_name) + should_link = if event.tag? + project.repository.tag_exists?(event.ref_name) + else + project.repository.branch_exists?(event.ref_name) + end + + should_link ? commits_link : nil + end + + def commit_create_mr_path(event) + if event.new_ref? && + create_mr_button_from_event?(event) && + event.authored_by?(current_user) + create_mr_path_from_push_event(event) + end + end + + def resource_parent_type(event) + if event.project + "project" + elsif event.group + "group" + end + end + end +end diff --git a/app/serializers/profile/event_serializer.rb b/app/serializers/profile/event_serializer.rb new file mode 100644 index 00000000000..c7f23d61fe1 --- /dev/null +++ b/app/serializers/profile/event_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Profile + class EventSerializer < BaseSerializer + entity Profile::EventEntity + end +end |