diff --git a/ee/app/assets/stylesheets/components/design_management/design.scss b/app/assets/stylesheets/components/design_management/design.scss
similarity index 100%
rename from ee/app/assets/stylesheets/components/design_management/design.scss
rename to app/assets/stylesheets/components/design_management/design.scss
diff --git a/ee/app/assets/stylesheets/components/design_management/design_list_item.scss b/app/assets/stylesheets/components/design_management/design_list_item.scss
similarity index 100%
rename from ee/app/assets/stylesheets/components/design_management/design_list_item.scss
rename to app/assets/stylesheets/components/design_management/design_list_item.scss
diff --git a/ee/app/assets/stylesheets/components/design_management/design_version_dropdown.scss b/app/assets/stylesheets/components/design_management/design_version_dropdown.scss
similarity index 100%
rename from ee/app/assets/stylesheets/components/design_management/design_version_dropdown.scss
rename to app/assets/stylesheets/components/design_management/design_version_dropdown.scss
diff --git a/app/views/projects/issues/_design_management.html.haml b/app/views/projects/issues/_design_management.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..96f1dc0155c49926c7553e045370a8b3cca0205e
--- /dev/null
+++ b/app/views/projects/issues/_design_management.html.haml
@@ -0,0 +1,15 @@
+- if @project.design_management_enabled?
+ .js-design-management{ data: { project_path: @project.full_path, issue_iid: @issue.iid, issue_path: project_issue_path(@project, @issue) } }
+- else
+ .mt-4
+ .row.empty-state
+ .col-12
+ .text-content
+ %h4.center
+ = _('The one place for your designs')
+ %p.center
+ - requirements_link_url = help_page_path('user/project/issues/design_management', anchor: 'requirements')
+ - requirements_link_start = ''.html_safe % { url: requirements_link_url }
+ - support_link_start = ''.html_safe % { url: support_url }
+ - link_end = ''.html_safe
+ = s_("DesignManagement|To enable design management, you'll need to %{requirements_link_start}meet the requirements%{requirements_link_end}. If you need help, reach out to our %{support_link_start}support team%{support_link_end} for assistance.").html_safe % { requirements_link_start: requirements_link_start, requirements_link_end: link_end, support_link_start: support_link_start, support_link_end: link_end }
diff --git a/app/views/projects/issues/_tabs.html.haml b/app/views/projects/issues/_tabs.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..d998a01623ffd68216c84b89a9d371c0d894fb91
--- /dev/null
+++ b/app/views/projects/issues/_tabs.html.haml
@@ -0,0 +1,14 @@
+%ul.nav-tabs.nav.nav-links{ role: 'tablist' }
+ %li
+ = link_to '#discussion-tab', class: 'active js-issue-tabs', id: 'discussion', role: 'tab', 'aria-controls': 'js-discussion', 'aria-selected': 'true', data: { toggle: 'tab', target: '#discussion-tab', qa_selector: 'discussion_tab_link' } do
+ = _('Discussion')
+ %span.badge.badge-pill.js-discussions-count
+ %li
+ = link_to '#designs-tab', class: 'js-issue-tabs', id: 'designs', role: 'tab', 'aria-controls': 'js-designs', 'aria-selected': 'false', data: { toggle: 'tab', target: '#designs-tab', qa_selector: 'designs_tab_link' } do
+ = _('Designs')
+ %span.badge.badge-pill.js-designs-count
+.tab-content
+ #discussion-tab.tab-pane.show.active{ role: 'tabpanel', 'aria-labelledby': 'discussion', data: { qa_selector: 'discussion_tab_content' } }
+ = render 'projects/issues/discussion'
+ #designs-tab.tab-pane{ role: 'tabpanel', 'aria-labelledby': 'designs', data: { qa_selector: 'designs_tab_content' } }
+ = render 'projects/issues/design_management'
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index 5f596ea79204aa68fb01ffd69c04ce563698c909..c8ffa2e3720a501d7cd683ba04b430d41e67f890 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -93,6 +93,6 @@
#js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@issue), notes_filters: UserPreference.notes_filters.to_json } }
= render 'new_branch' if show_new_branch_button?
- = render_if_exists 'projects/issues/discussion'
+ = render 'projects/issues/tabs'
= render 'shared/issuable/sidebar', issuable_sidebar: @issuable_sidebar, assignees: @issue.assignees
diff --git a/changelogs/unreleased/design-management-ee-to-ce-fe-designs-tab.yml b/changelogs/unreleased/design-management-ee-to-ce-fe-designs-tab.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e624746ec33dc98d81d2d9cff9c19c51cb641c53
--- /dev/null
+++ b/changelogs/unreleased/design-management-ee-to-ce-fe-designs-tab.yml
@@ -0,0 +1,5 @@
+---
+title: Add Design Management (via Designs tab on Issues) to GitLab FOSS
+merge_request: 31309
+author:
+type: added
diff --git a/ee/app/views/projects/issues/_discussion.html.haml b/ee/app/views/projects/issues/_discussion.html.haml
deleted file mode 100644
index e0711912b9e880fb92ac6316353f6dd2d5691bc1..0000000000000000000000000000000000000000
--- a/ee/app/views/projects/issues/_discussion.html.haml
+++ /dev/null
@@ -1,28 +0,0 @@
-%ul.nav-tabs.nav.nav-links{ role: 'tablist' }
- %li
- = link_to '#discussion-tab', class: 'active js-issue-tabs', id: 'discussion', role: 'tab', 'aria-controls': 'js-discussion', 'aria-selected': 'true', data: { toggle: 'tab', target: '#discussion-tab' } do
- = _('Discussion')
- %span.badge.badge-pill.js-discussions-count
- %li
- = link_to '#designs-tab', class: 'js-issue-tabs', id: 'designs', role: 'tab', 'aria-controls': 'js-designs', 'aria-selected': 'false', data: { toggle: 'tab', target: '#designs-tab', qa_selector: 'designs_tab_link' } do
- = _('Designs')
- %span.badge.badge-pill.js-designs-count
-.tab-content
- #discussion-tab.tab-pane.show.active{ role: 'tabpanel', 'aria-labelledby': 'discussion' }
- = render_ce 'projects/issues/discussion'
- #designs-tab.tab-pane{ role: 'tabpanel', 'aria-labelledby': 'designs', data: { qa_selector: 'designs_tab_content'} }
- - if @project.design_management_enabled?
- .js-design-management{ data: { project_path: @project.full_path, issue_iid: @issue.iid, issue_path: project_issue_path(@project, @issue) } }
- - else
- .mt-4
- .row.empty-state
- .col-12
- .text-content
- %h4.center
- = _('The one place for your designs')
- %p.center
- - requirements_link_url = help_page_path('user/project/issues/design_management', anchor: 'requirements')
- - requirements_link_start = ''.html_safe % { url: requirements_link_url }
- - support_link_start = ''.html_safe % { url: EE::CUSTOMER_SUPPORT_URL }
- - link_end = ''.html_safe
- = s_("DesignManagement|To enable design management, you'll need to %{requirements_link_start}meet the requirements%{requirements_link_end}. If you need help, reach out to our %{support_link_start}support team%{support_link_end} for assistance.").html_safe % { requirements_link_start: requirements_link_start, requirements_link_end: link_end, support_link_start: support_link_start, support_link_end: link_end }
diff --git a/qa/qa.rb b/qa/qa.rb
index 9a7d2cb0f2a97657b343f943b1ffe0427181d5a5..a8c666e0eab4d1f9a1c8b52de168a8c58e3bbcb4 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -418,6 +418,7 @@ module Component
autoload :Note, 'qa/page/component/note'
autoload :ConfirmModal, 'qa/page/component/confirm_modal'
autoload :CustomMetric, 'qa/page/component/custom_metric'
+ autoload :DesignManagement, 'qa/page/component/design_management'
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
diff --git a/qa/qa/ee.rb b/qa/qa/ee.rb
index 4258468389ca7a7941f0354ea9f71585fa2fab79..cb1ed634e8480bed542a8c530377e8073c237615 100644
--- a/qa/qa/ee.rb
+++ b/qa/qa/ee.rb
@@ -13,7 +13,6 @@ module Runtime
module Page
module Component
- autoload :DesignManagement, 'qa/ee/page/component/design_management'
autoload :LicenseManagement, 'qa/ee/page/component/license_management'
autoload :SecureReport, 'qa/ee/page/component/secure_report'
diff --git a/qa/qa/ee/page/component/design_management.rb b/qa/qa/ee/page/component/design_management.rb
deleted file mode 100644
index 2f8bac914196e214d32ef650868250aadab9894d..0000000000000000000000000000000000000000
--- a/qa/qa/ee/page/component/design_management.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module EE
- module Page
- module Component
- module DesignManagement
- def self.prepended(page)
- page.module_eval do
- view 'ee/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue' do
- element :design_discussion_content
- end
-
- view 'ee/app/assets/javascripts/design_management/components/design_notes/design_note.vue' do
- element :note_content
- end
-
- view 'ee/app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue' do
- element :note_textarea
- element :save_comment_button
- end
-
- view 'ee/app/assets/javascripts/design_management/components/design_overlay.vue' do
- element :design_image_button
- end
-
- view 'ee/app/assets/javascripts/design_management/components/list/item.vue' do
- element :design_file_name
- element :design_image
- end
- end
- end
-
- def add_annotation(note)
- click_element(:design_image_button)
- fill_element(:note_textarea, note)
- click_element(:save_comment_button)
-
- # It takes a moment for the annotation to be saved.
- # We'll check for the annotation in a test, but here we'll at least
- # wait for the "Save comment" button to disappear
- saved = has_no_element?(:save_comment_button)
-
- raise ExpectationNotMet, %q(There was a problem while adding the annotation) unless saved
- end
-
- def add_design(design_file_path)
- # `attach_file` doesn't seem able to find element via data attributes.
- # It accepts a `class:` option, but that only works for class attributes
- # It doesn't work as a CSS selector.
- # So instead we use the name attribute as a locator
- page.attach_file("design_file", design_file_path, make_visible: { display: 'block' })
-
- filename = ::File.basename(design_file_path)
-
- found = wait_until(reload: false, sleep_interval: 1) do
- image = find_element(:design_image)
-
- has_element?(:design_file_name, text: filename) &&
- image["complete"] &&
- image["naturalWidth"].to_i > 0
- end
-
- raise ElementNotFound, %Q(Attempted to attach design "#{filename}" but it did not appear) unless found
- end
-
- def click_design(filename)
- click_element(:design_file_name, text: filename)
- end
-
- def has_annotation?(note)
- within_element_by_index(:design_discussion_content, 0) do
- has_element?(:note_content, text: note)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/ee/page/project/issue/show.rb b/qa/qa/ee/page/project/issue/show.rb
index 5ea9549620b2b9559d438be4c906019892b130db..31036069318a401c7a74c0027746eae24ec4f061 100644
--- a/qa/qa/ee/page/project/issue/show.rb
+++ b/qa/qa/ee/page/project/issue/show.rb
@@ -6,8 +6,6 @@ module Page
module Project
module Issue
module Show
- include Page::Component::DesignManagement
-
def self.prepended(page)
page.module_eval do
view 'ee/app/assets/javascripts/related_issues/components/add_issuable_form.vue' do
@@ -34,19 +32,9 @@ def self.prepended(page)
element :weight_input_field
element :weight_no_value_content
end
-
- view 'ee/app/views/projects/issues/_discussion.html.haml' do
- element :designs_tab_link
- element :designs_tab_content
- end
end
end
- def click_designs_tab
- click_element(:designs_tab_link)
- active_element?(:designs_tab_content)
- end
-
def click_remove_weight_link
click_element(:remove_weight_link)
end
diff --git a/qa/qa/page/component/design_management.rb b/qa/qa/page/component/design_management.rb
new file mode 100644
index 0000000000000000000000000000000000000000..e61003cf350226a68e3f37bd26fd9121240df82e
--- /dev/null
+++ b/qa/qa/page/component/design_management.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module DesignManagement
+ def self.prepended(page)
+ page.module_eval do
+ view 'app/assets/javascripts/design_management/components/design_notes/design_discussion.vue' do
+ element :design_discussion_content
+ end
+
+ view 'app/assets/javascripts/design_management/components/design_notes/design_note.vue' do
+ element :note_content
+ end
+
+ view 'app/assets/javascripts/design_management/components/design_notes/design_reply_form.vue' do
+ element :note_textarea
+ element :save_comment_button
+ end
+
+ view 'app/assets/javascripts/design_management/components/design_overlay.vue' do
+ element :design_image_button
+ end
+
+ view 'app/assets/javascripts/design_management/components/list/item.vue' do
+ element :design_file_name
+ element :design_image
+ end
+ end
+ end
+
+ def add_annotation(note)
+ click_element(:design_image_button)
+ fill_element(:note_textarea, note)
+ click_element(:save_comment_button)
+
+ # It takes a moment for the annotation to be saved.
+ # We'll check for the annotation in a test, but here we'll at least
+ # wait for the "Save comment" button to disappear
+ saved = has_no_element?(:save_comment_button)
+
+ raise ExpectationNotMet, %q(There was a problem while adding the annotation) unless saved
+ end
+
+ def add_design(design_file_path)
+ # `attach_file` doesn't seem able to find element via data attributes.
+ # It accepts a `class:` option, but that only works for class attributes
+ # It doesn't work as a CSS selector.
+ # So instead we use the name attribute as a locator
+ page.attach_file("design_file", design_file_path, make_visible: { display: 'block' })
+
+ filename = ::File.basename(design_file_path)
+
+ found = wait_until(reload: false, sleep_interval: 1) do
+ image = find_element(:design_image)
+
+ has_element?(:design_file_name, text: filename) &&
+ image["complete"] &&
+ image["naturalWidth"].to_i > 0
+ end
+
+ raise ElementNotFound, %Q(Attempted to attach design "#{filename}" but it did not appear) unless found
+ end
+
+ def click_design(filename)
+ click_element(:design_file_name, text: filename)
+ end
+
+ def has_annotation?(note)
+ within_element_by_index(:design_discussion_content, 0) do
+ has_element?(:note_content, text: note)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 8365ecb63489fe5d1d9e17a38e05a7c4222fa824..dd74ff28763560401319ff0c84d67db4fd250d51 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -7,6 +7,7 @@ module Issue
class Show < Page::Base
include Page::Component::Issuable::Common
include Page::Component::Note
+ include Page::Component::DesignManagement
view 'app/assets/javascripts/notes/components/comment_form.vue' do
element :comment_button
@@ -56,6 +57,23 @@ class Show < Page::Base
element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
end
+ view 'app/views/projects/issues/_tabs.html.haml' do
+ element :discussion_tab_link
+ element :discussion_tab_content
+ element :designs_tab_link
+ element :designs_tab_content
+ end
+
+ def click_discussion_tab
+ click_element(:discussion_tab_link)
+ active_element?(:discussion_tab_content)
+ end
+
+ def click_designs_tab
+ click_element(:designs_tab_link)
+ active_element?(:designs_tab_content)
+ end
+
def click_milestone_link
click_element(:milestone_link)
end
diff --git a/qa/qa/specs/features/ee/browser_ui/3_create/design_management_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_add_annotation.rb
similarity index 95%
rename from qa/qa/specs/features/ee/browser_ui/3_create/design_management_spec.rb
rename to qa/qa/specs/features/browser_ui/3_create/design_management/add_design_add_annotation.rb
index 084ac7ec0fd6f5376720d990a3d65dff771d8092..b50edcfcf088057c71490c15a3a3a7ffce742e77 100644
--- a/qa/qa/specs/features/ee/browser_ui/3_create/design_management_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_add_annotation.rb
@@ -22,6 +22,8 @@ module QA
show.add_annotation(annotation)
expect(show).to have_annotation(annotation)
+
+ show.click_discussion_tab
end
end
end