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