From db85d9d870d77c9ea7c2aa1aa843c2fc1062f9fc Mon Sep 17 00:00:00 2001
From: Justin Ho Tuan Duong <hduong@gitlab.com>
Date: Fri, 10 May 2024 19:48:18 +0000
Subject: [PATCH] Add visual indicators for some items

Issues, Epics, MRs. Verified that Notes and User activities work
as expected.

Changelog: changed
---
 .../graphql/fragments/design.fragment.graphql |  1 +
 app/assets/javascripts/issues/show/index.js   |  2 ++
 .../notes/components/note_header.vue          |  2 +-
 .../queries/snippet/snippet.query.graphql     |  1 +
 app/helpers/issuables_helper.rb               |  1 +
 app/helpers/merge_requests_helper.rb          | 23 ++++++++--------
 app/views/events/_event.html.haml             |  4 +--
 .../import/shared/_imported_badge.html.haml   |  7 +++++
 .../import/shared/_imported_text.html.haml    |  3 ---
 .../projects/merge_requests/_mr_box.html.haml |  2 +-
 .../projects/merge_requests/_page.html.haml   |  2 +-
 app/views/shared/notes/_note.html.haml        |  2 ++
 doc/user/group/import/index.md                |  3 +++
 ee/spec/helpers/ee/issuables_helper_spec.rb   |  1 +
 .../design/__snapshots__/index_spec.js.snap   |  1 +
 spec/frontend/snippets/test_utils.js          |  1 +
 spec/helpers/issuables_helper_spec.rb         |  1 +
 spec/helpers/merge_requests_helper_spec.rb    | 26 +++++++++++++++++++
 18 files changed, 64 insertions(+), 19 deletions(-)
 create mode 100644 app/views/import/shared/_imported_badge.html.haml
 delete mode 100644 app/views/import/shared/_imported_text.html.haml

diff --git a/app/assets/javascripts/design_management/graphql/fragments/design.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/design.fragment.graphql
index 4b1703e41c34c..47ea165470f3d 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/design.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/design.fragment.graphql
@@ -6,6 +6,7 @@
 fragment DesignItem on Design {
   ...DesignListItem
   fullPath
+  imported
   diffRefs {
     ...DesignDiffRefs
   }
diff --git a/app/assets/javascripts/issues/show/index.js b/app/assets/javascripts/issues/show/index.js
index b1d8a245f5ef2..985f6fab7ed64 100644
--- a/app/assets/javascripts/issues/show/index.js
+++ b/app/assets/javascripts/issues/show/index.js
@@ -46,6 +46,7 @@ export function initIssuableApp(store) {
     issuableId,
     issueType,
     hasIterationsFeature,
+    imported,
     // for issue
     registerPath,
     signInPath,
@@ -129,6 +130,7 @@ export function initIssuableApp(store) {
           descriptionComponent: issueType === TYPE_INCIDENT ? IncidentTabs : DescriptionComponent,
           isConfidential: this.getNoteableData?.confidential,
           isLocked: this.getNoteableData?.discussion_locked,
+          isImported: imported,
           issuableStatus: this.getNoteableData?.state,
           issuableType: issueType,
           issueId: this.getNoteableData?.id?.toString(),
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index 15822be228990..bf420dc045709 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -247,7 +247,7 @@ export default {
       </template>
 
       <template v-if="isImported">
-        <span>·</span>
+        <span v-if="isSystemNote">&middot;</span>
         <imported-badge :text-only="isSystemNote" :importable-type="importableType" size="sm" />
       </template>
 
diff --git a/app/graphql/queries/snippet/snippet.query.graphql b/app/graphql/queries/snippet/snippet.query.graphql
index 8a2b314b994be..2f4b89b339966 100644
--- a/app/graphql/queries/snippet/snippet.query.graphql
+++ b/app/graphql/queries/snippet/snippet.query.graphql
@@ -14,6 +14,7 @@ query GetSnippetQuery($ids: [SnippetID!]) {
       httpUrlToRepo
       sshUrlToRepo
       hidden
+      imported
       blobs {
         __typename
         hasUnretrievableBlobs
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index ccf208d5f3ea8..3c81142a88489 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -164,6 +164,7 @@ def issuable_initial_data(issuable)
       canUpdate: can?(current_user, :"update_#{issuable.to_ability_name}", issuable),
       canDestroy: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable),
       issuableRef: issuable.to_reference,
+      imported: issuable.imported?,
       markdownPreviewPath: preview_markdown_path(parent, target_type: issuable.model_name, target_id: issuable.iid),
       markdownDocsPath: help_page_path('user/markdown'),
       lockVersion: issuable.lock_version,
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index a3b2614a1a4e4..39211a518a184 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -311,23 +311,24 @@ def merge_request_header(project, merge_request)
     _('%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}').html_safe % { author: link_to_author.html_safe, source_branch: merge_request_source_branch(merge_request).html_safe, copy_button: copy_button.html_safe, target_branch: target_branch.html_safe, created_at: time_ago_with_tooltip(merge_request.created_at, html_class: 'gl-display-inline-block').html_safe }
   end
 
-  def sticky_header_data
+  def sticky_header_data(project, merge_request)
     data = {
-      iid: @merge_request.iid,
-      projectPath: @project.full_path,
-      sourceProjectPath: @merge_request.source_project_path,
-      title: markdown_field(@merge_request, :title),
+      iid: merge_request.iid,
+      projectPath: project.full_path,
+      sourceProjectPath: merge_request.source_project_path,
+      title: markdown_field(merge_request, :title),
       isFluidLayout: fluid_layout.to_s,
-      blocksMerge: @project.only_allow_merge_if_all_discussions_are_resolved?.to_s,
+      blocksMerge: project.only_allow_merge_if_all_discussions_are_resolved?.to_s,
+      imported: merge_request.imported?.to_s,
       tabs: [
-        ['show', _('Overview'), project_merge_request_path(@project, @merge_request), @merge_request.related_notes.user.count],
-        ['commits', _('Commits'), commits_project_merge_request_path(@project, @merge_request), @commits_count],
-        ['diffs', _('Changes'), diffs_project_merge_request_path(@project, @merge_request), @diffs_count]
+        ['show', _('Overview'), project_merge_request_path(project, merge_request), merge_request.related_notes.user.count],
+        ['commits', _('Commits'), commits_project_merge_request_path(project, merge_request), @commits_count],
+        ['diffs', _('Changes'), diffs_project_merge_request_path(project, merge_request), @diffs_count]
       ]
     }
 
-    if @project.builds_enabled?
-      data[:tabs].insert(2, ['pipelines', _('Pipelines'), pipelines_project_merge_request_path(@project, @merge_request), @number_of_pipelines])
+    if project.builds_enabled?
+      data[:tabs].insert(2, ['pipelines', _('Pipelines'), pipelines_project_merge_request_path(project, merge_request), @number_of_pipelines])
     end
 
     data
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 432070ed28a15..3bb97720e845a 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -5,8 +5,8 @@
     .event-item-timestamp.gl-font-sm
       #{time_ago_with_tooltip(event.created_at)}
       - if event.imported?
-        %span •
-        = render "import/shared/imported_text", importable: _('event')
+        %span &middot;
+        = render "import/shared/imported_badge", text_only: true, importable: _('event')
 
     - if event.wiki_page?
       = render "events/event/wiki", event: event
diff --git a/app/views/import/shared/_imported_badge.html.haml b/app/views/import/shared/_imported_badge.html.haml
new file mode 100644
index 0000000000000..8da76d45019b9
--- /dev/null
+++ b/app/views/import/shared/_imported_badge.html.haml
@@ -0,0 +1,7 @@
+- tooltip_title = safe_format(s_('BulkImport|This %{importable} was imported from another instance.'), importable: local_assigns[:importable])
+- text_only = local_assigns.fetch(:text_only, false)
+
+- if text_only
+  %span.has-tooltip.gl-line-height-normal.gl-font-sm{ title: tooltip_title }= _('Imported')
+- else
+  = render Pajamas::BadgeComponent.new(_('Imported'), size: :sm, title: tooltip_title, class: 'has-tooltip')
diff --git a/app/views/import/shared/_imported_text.html.haml b/app/views/import/shared/_imported_text.html.haml
deleted file mode 100644
index cac62c6fb4954..0000000000000
--- a/app/views/import/shared/_imported_text.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- tooltip_title = safe_format(s_('BulkImport|This %{importable} was imported from another instance.'), importable: local_assigns[:importable])
-
-%span.has-tooltip.gl-line-height-normal.gl-font-sm{ title: tooltip_title }= _('Imported')
diff --git a/app/views/projects/merge_requests/_mr_box.html.haml b/app/views/projects/merge_requests/_mr_box.html.haml
index c98252ef63ccb..6a6771497e63c 100644
--- a/app/views/projects/merge_requests/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/_mr_box.html.haml
@@ -1,3 +1,3 @@
 .detail-page-description.gl-pt-2.gl-pb-4.gl-display-flex.gl-align-items-baseline.gl-flex-wrap{ class: "#{'is-merge-request' if !fluid_layout}" }
-  .js-mr-header{ data: { project_path: @merge_request.project.path_with_namespace, hidden: @merge_request.hidden?.to_s, iid: @merge_request.iid, state: @merge_request.state } }
+  .js-mr-header{ data: { project_path: @merge_request.project.path_with_namespace, hidden: @merge_request.hidden?.to_s, imported: @merge_request.imported?.to_s, iid: @merge_request.iid, state: @merge_request.state } }
   = merge_request_header(@project, @merge_request)
diff --git a/app/views/projects/merge_requests/_page.html.haml b/app/views/projects/merge_requests/_page.html.haml
index e63ae75c1b82a..d7c0592b8353e 100644
--- a/app/views/projects/merge_requests/_page.html.haml
+++ b/app/views/projects/merge_requests/_page.html.haml
@@ -21,7 +21,7 @@
 
 .merge-request{ data: { mr_action: mr_action, url: merge_request_path(@merge_request, format: :json), project_path: project_path(@merge_request.project), lock_version: @merge_request.lock_version, diffs_batch_cache_key: @diffs_batch_cache_key } }
   = render "projects/merge_requests/mr_title"
-  #js-merge-sticky-header{ data: { data: sticky_header_data.to_json } }
+  #js-merge-sticky-header{ data: { data: sticky_header_data(@project, @merge_request).to_json } }
   .merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
     = render "projects/merge_requests/mr_box"
     .gl-static.merge-request-tabs-holder{ class: "#{'js-tabs-affix' unless ENV['RAILS_ENV'] == 'test'}" }
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index ec304c58fcea4..32e7041c63f0e 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -45,6 +45,8 @@
               %span.system-note-separator.gl-display-none.gl-sm-display-inline
                 &middot;
               %a.system-note-separator{ href: "##{dom_id(note)}" }= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago')
+            - if note.imported?
+              = render "import/shared/imported_badge", importable: note.system? ? _('activity') : _('comment')
         - unless note.system?
           .note-actions
             - if note.for_personal_snippet?
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 93b3a38766c3a..a5ee516ed4df1 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -303,6 +303,7 @@ To view group import history:
 > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429109) in GitLab 16.6 [with a flag](../../feature_flags.md) named `bulk_import_details_page`. Enabled by default.
 > - Feature flag `bulk_import_details_page` removed in GitLab 16.8.
 > - Details for partially completed and completed imports [added](https://gitlab.com/gitlab-org/gitlab/-/issues/437874) in GitLab 16.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/443492) in GitLab 17.0, an **Imported** badge to indicate that designs, epics, issues, merge requests, notes (system notes and comments), snippets, and user profile activity were imported.
 
 To review the results of an import:
 
@@ -310,6 +311,8 @@ To review the results of an import:
 1. To see the details of a failed import, select the **See failures** link on any import with a **Failed** or **Partially completed** status.
 1. If the import has a **Partially completed** or **Complete** status, to see which items were and were not imported, select **Details**.
 
+You can also see that an item was imported when you see an **Imported** badge on some items in the GitLab UI.
+
 ## Cancel a running import
 
 To cancel a running import:
diff --git a/ee/spec/helpers/ee/issuables_helper_spec.rb b/ee/spec/helpers/ee/issuables_helper_spec.rb
index 06bae9c0725a2..2b763c5d60ce9 100644
--- a/ee/spec/helpers/ee/issuables_helper_spec.rb
+++ b/ee/spec/helpers/ee/issuables_helper_spec.rb
@@ -38,6 +38,7 @@
           initialTitleHtml: epic.title,
           initialTitleText: epic.title,
           issuableRef: "&#{epic.iid}",
+          imported: epic.imported?,
           issuableTemplateNamesPath: '',
           issueLinksEndpoint: "/groups/#{@group.full_path}/-/epics/#{epic.iid}/issues",
           issuesWebUrl: "/groups/#{@group.full_path}/-/issues",
diff --git a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
index 7f2e45076e515..fe862eec78f02 100644
--- a/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
+++ b/spec/frontend/design_management/pages/design/__snapshots__/index_spec.js.snap
@@ -21,6 +21,7 @@ exports[`Design management design index page when loaded renders design index 1`
       iid="1"
       image="test.jpg"
       imagev432x230="test.jpg"
+      imported="true"
       islatestversion="true"
       issidebaropen="true"
       issue="[object Object]"
diff --git a/spec/frontend/snippets/test_utils.js b/spec/frontend/snippets/test_utils.js
index 9d42e9fa26c53..dfa8d309ec0b3 100644
--- a/spec/frontend/snippets/test_utils.js
+++ b/spec/frontend/snippets/test_utils.js
@@ -46,6 +46,7 @@ export const createGQLSnippet = () => ({
     },
   },
   hidden: false,
+  imported: false,
 });
 
 export const createGQLSnippetsQueryResponse = (snippets) => ({
diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb
index cb6fcaa9d6506..c813bc98590a6 100644
--- a/spec/helpers/issuables_helper_spec.rb
+++ b/spec/helpers/issuables_helper_spec.rb
@@ -252,6 +252,7 @@
           canUpdate: true,
           canDestroy: true,
           issuableRef: "##{issue.iid}",
+          imported: issue.imported?,
           markdownPreviewPath: "/#{@project.full_path}/preview_markdown?target_id=#{issue.iid}&target_type=Issue",
           markdownDocsPath: '/help/user/markdown',
           lockVersion: issue.lock_version,
diff --git a/spec/helpers/merge_requests_helper_spec.rb b/spec/helpers/merge_requests_helper_spec.rb
index a2f2a1db113ac..2db156d273206 100644
--- a/spec/helpers/merge_requests_helper_spec.rb
+++ b/spec/helpers/merge_requests_helper_spec.rb
@@ -10,6 +10,7 @@
   include ProjectForksHelper
   include IconsHelper
   include IssuablesHelper
+  include MarkupHelper
 
   let_it_be(:current_user) { create(:user) }
 
@@ -218,6 +219,31 @@
     end
   end
 
+  describe '#sticky_header_data' do
+    let_it_be(:project) { create(:project) }
+    let(:merge_request) do
+      create(:merge_request, source_project: project, target_project: project, imported_from: imported_from)
+    end
+
+    subject { sticky_header_data(project, merge_request) }
+
+    context 'when the merge request is not imported' do
+      let(:imported_from) { :none }
+
+      it 'returns data with imported set as false' do
+        expect(subject[:imported]).to eq('false')
+      end
+    end
+
+    context 'when the merge request is imported' do
+      let(:imported_from) { :gitlab_migration }
+
+      it 'returns data with imported set as true' do
+        expect(subject[:imported]).to eq('true')
+      end
+    end
+  end
+
   describe '#tab_count_display' do
     let(:merge_request) { create(:merge_request) }
 
-- 
GitLab