From d09e4c5cd75638afea7a7f561a30ea0e6f23cf17 Mon Sep 17 00:00:00 2001 From: Julia Miocene Date: Thu, 29 Aug 2024 16:31:08 +0200 Subject: [PATCH 1/5] Add EmptyResult vue and rails component --- .../components/empty_result.stories.js | 23 +++++++++ .../vue_shared/components/empty_result.vue | 51 +++++++++++++++++++ .../layouts/empty_result_component.haml | 14 +++++ .../layouts/empty_result_component.rb | 32 ++++++++++++ .../layouts/empty_result_component_spec.rb | 19 +++++++ .../layouts/empty_result_component_preview.rb | 9 ++++ .../components/empty_result_spec.js | 36 +++++++++++++ 7 files changed, 184 insertions(+) create mode 100644 app/assets/javascripts/vue_shared/components/empty_result.stories.js create mode 100644 app/assets/javascripts/vue_shared/components/empty_result.vue create mode 100644 app/components/layouts/empty_result_component.haml create mode 100644 app/components/layouts/empty_result_component.rb create mode 100644 spec/components/layouts/empty_result_component_spec.rb create mode 100644 spec/components/previews/layouts/empty_result_component_preview.rb create mode 100644 spec/frontend/vue_shared/components/empty_result_spec.js diff --git a/app/assets/javascripts/vue_shared/components/empty_result.stories.js b/app/assets/javascripts/vue_shared/components/empty_result.stories.js new file mode 100644 index 00000000000000..0571ed47b56152 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/empty_result.stories.js @@ -0,0 +1,23 @@ +import EmptyResult, { TYPES } from './empty_result.vue'; + +export default { + component: EmptyResult, + title: 'vue_shared/empty_result', + argTypes: { + type: { + control: 'select', + options: Object.values(TYPES), + }, + }, +}; + +const Template = (args, { argTypes }) => ({ + components: { EmptyResult }, + props: Object.keys(argTypes), + template: ``, +}); + +export const Default = Template.bind({}); +Default.args = { + type: TYPES.search, +}; diff --git a/app/assets/javascripts/vue_shared/components/empty_result.vue b/app/assets/javascripts/vue_shared/components/empty_result.vue new file mode 100644 index 00000000000000..d4ea878856ddfe --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/empty_result.vue @@ -0,0 +1,51 @@ + + + diff --git a/app/components/layouts/empty_result_component.haml b/app/components/layouts/empty_result_component.haml new file mode 100644 index 00000000000000..398a8925b3c715 --- /dev/null +++ b/app/components/layouts/empty_result_component.haml @@ -0,0 +1,14 @@ +- if filter? + = render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-state/empty-search-md.svg', + title: _('Sorry, your filter produced no results'), + empty_state_options: { **@html_options }) do |c| + + - c.with_description do + = _('To widen your search, change or remove filters above') +- else + = render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-state/empty-search-md.svg', + title: _('No results found'), + empty_state_options: { **@html_options }) do |c| + + - c.with_description do + = _('Edit your search and try again') diff --git a/app/components/layouts/empty_result_component.rb b/app/components/layouts/empty_result_component.rb new file mode 100644 index 00000000000000..fe1fa985612216 --- /dev/null +++ b/app/components/layouts/empty_result_component.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Layouts + class EmptyResultComponent < ViewComponent::Base + TYPE_OPTIONS = [:search, :filter].freeze + + # @param [Symbol] type + # @param [Hash] html_options + def initialize( + type: :search, + **html_options + ) + @type = filter_attribute(type.to_sym, TYPE_OPTIONS, default: :search) + @html_options = html_options + end + + def filter_attribute(value, allowed_values, default: nil) + return default unless value + return value if allowed_values.include?(value) + + default + end + + def filter? + @type == :filter + end + + def html_options + format_options(options: @html_options) + end + end +end diff --git a/spec/components/layouts/empty_result_component_spec.rb b/spec/components/layouts/empty_result_component_spec.rb new file mode 100644 index 00000000000000..1213807def68db --- /dev/null +++ b/spec/components/layouts/empty_result_component_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Layouts::EmptyResultComponent, type: :component, feature_category: :shared do + it 'renders search empty result' do + render_inline described_class.new(type: 'search') + + expect(page).to have_css('.gl-empty-state', text: 'No results found') + expect(page).to have_css('.gl-empty-state', text: 'Edit your search and try again') + end + + it 'renders filter empty result' do + render_inline described_class.new(type: 'filter') + + expect(page).to have_css('.gl-empty-state', text: 'Sorry, your filter produced no results') + expect(page).to have_css('.gl-empty-state', text: 'To widen your search, change or remove filters above') + end +end diff --git a/spec/components/previews/layouts/empty_result_component_preview.rb b/spec/components/previews/layouts/empty_result_component_preview.rb new file mode 100644 index 00000000000000..de584f77ff5906 --- /dev/null +++ b/spec/components/previews/layouts/empty_result_component_preview.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Layouts + class EmptyResultComponentPreview < ViewComponent::Preview + def default + render(::Layouts::EmptyResultComponent.new) + end + end +end diff --git a/spec/frontend/vue_shared/components/empty_result_spec.js b/spec/frontend/vue_shared/components/empty_result_spec.js new file mode 100644 index 00000000000000..e3b3459258d2e6 --- /dev/null +++ b/spec/frontend/vue_shared/components/empty_result_spec.js @@ -0,0 +1,36 @@ +import emptyStateSvgPath from '@gitlab/svgs/dist/illustrations/empty-state/empty-search-md.svg'; +import { GlEmptyState } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import EmptyResult from '~/vue_shared/components/empty_result.vue'; + +describe('Empty result', () => { + let wrapper; + + const createComponent = (props) => { + wrapper = shallowMountExtended(EmptyResult, { + propsData: props, + }); + }; + + const findEmptyState = () => wrapper.findComponent(GlEmptyState); + + it('renders empty search state', () => { + createComponent({ type: 'search' }); + + expect(findEmptyState().props()).toMatchObject({ + svgPath: emptyStateSvgPath, + title: 'No results found', + description: 'Edit your search and try again', + }); + }); + + it('renders empty filter state', () => { + createComponent({ type: 'filter' }); + + expect(findEmptyState().props()).toMatchObject({ + svgPath: emptyStateSvgPath, + title: 'Sorry, your filter produced no results', + description: 'To widen your search, change or remove filters above', + }); + }); +}); -- GitLab From 258bbda530e2af87cb0444c1a36945b9a2765cb0 Mon Sep 17 00:00:00 2001 From: Julia Miocene Date: Fri, 30 Aug 2024 11:07:18 +0200 Subject: [PATCH 2/5] Apply suggestions --- .../layouts/empty_result_component.haml | 20 ++++++++----------- .../layouts/empty_result_component.rb | 9 +-------- .../components/empty_result_spec.js | 4 ++-- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/app/components/layouts/empty_result_component.haml b/app/components/layouts/empty_result_component.haml index 398a8925b3c715..baece68128b0eb 100644 --- a/app/components/layouts/empty_result_component.haml +++ b/app/components/layouts/empty_result_component.haml @@ -1,14 +1,10 @@ -- if filter? - = render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-state/empty-search-md.svg', - title: _('Sorry, your filter produced no results'), - empty_state_options: { **@html_options }) do |c| +- title = filter? ? _('Sorry, your filter produced no results') : _('No results found') +- description = filter? ? _('To widen your search, change or remove filters above') : _('Edit your search and try again') +- svg_path = 'illustrations/empty-state/empty-search-md.svg' - - c.with_description do - = _('To widen your search, change or remove filters above') -- else - = render Pajamas::EmptyStateComponent.new(svg_path: 'illustrations/empty-state/empty-search-md.svg', - title: _('No results found'), - empty_state_options: { **@html_options }) do |c| += render Pajamas::EmptyStateComponent.new(svg_path: svg_path, + title: title, + empty_state_options: { **@html_options }) do |c| - - c.with_description do - = _('Edit your search and try again') + - c.with_description do + = description diff --git a/app/components/layouts/empty_result_component.rb b/app/components/layouts/empty_result_component.rb index fe1fa985612216..08aa5379beea8a 100644 --- a/app/components/layouts/empty_result_component.rb +++ b/app/components/layouts/empty_result_component.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Layouts - class EmptyResultComponent < ViewComponent::Base + class EmptyResultComponent < Pajamas::Component TYPE_OPTIONS = [:search, :filter].freeze # @param [Symbol] type @@ -14,13 +14,6 @@ def initialize( @html_options = html_options end - def filter_attribute(value, allowed_values, default: nil) - return default unless value - return value if allowed_values.include?(value) - - default - end - def filter? @type == :filter end diff --git a/spec/frontend/vue_shared/components/empty_result_spec.js b/spec/frontend/vue_shared/components/empty_result_spec.js index e3b3459258d2e6..0879c40e09f8ff 100644 --- a/spec/frontend/vue_shared/components/empty_result_spec.js +++ b/spec/frontend/vue_shared/components/empty_result_spec.js @@ -1,13 +1,13 @@ import emptyStateSvgPath from '@gitlab/svgs/dist/illustrations/empty-state/empty-search-md.svg'; import { GlEmptyState } from '@gitlab/ui'; -import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { shallowMount } from '@vue/test-utils'; import EmptyResult from '~/vue_shared/components/empty_result.vue'; describe('Empty result', () => { let wrapper; const createComponent = (props) => { - wrapper = shallowMountExtended(EmptyResult, { + wrapper = shallowMount(EmptyResult, { propsData: props, }); }; -- GitLab From 53fe70e5ec13a9199e8024193ac689d1b10cb60f Mon Sep 17 00:00:00 2001 From: Julia Miocene Date: Mon, 2 Sep 2024 10:46:40 +0200 Subject: [PATCH 3/5] Update tests --- .../layouts/empty_result_component_spec.rb | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/spec/components/layouts/empty_result_component_spec.rb b/spec/components/layouts/empty_result_component_spec.rb index 1213807def68db..cb365dca23b251 100644 --- a/spec/components/layouts/empty_result_component_spec.rb +++ b/spec/components/layouts/empty_result_component_spec.rb @@ -3,17 +3,28 @@ require 'spec_helper' RSpec.describe Layouts::EmptyResultComponent, type: :component, feature_category: :shared do - it 'renders search empty result' do - render_inline described_class.new(type: 'search') + let(:type) { :search } + let(:html_options) { { data: { testid: 'empty-result-test-id' } } } + + before do + render_inline described_class.new(type: type, **html_options) + end + it 'renders search empty result' do expect(page).to have_css('.gl-empty-state', text: 'No results found') expect(page).to have_css('.gl-empty-state', text: 'Edit your search and try again') end - it 'renders filter empty result' do - render_inline described_class.new(type: 'filter') + it 'renders custom attributes' do + expect(page).to have_css('[data-testid="empty-result-test-id"]') + end + + context 'when type is filter' do + let(:type) { :filter } - expect(page).to have_css('.gl-empty-state', text: 'Sorry, your filter produced no results') - expect(page).to have_css('.gl-empty-state', text: 'To widen your search, change or remove filters above') + it 'renders empty result' do + expect(page).to have_css('.gl-empty-state', text: 'Sorry, your filter produced no results') + expect(page).to have_css('.gl-empty-state', text: 'To widen your search, change or remove filters above') + end end end -- GitLab From 49afb8d660d407138bfc081747a3b3f984cd9d64 Mon Sep 17 00:00:00 2001 From: Julia Miocene Date: Thu, 5 Sep 2024 14:20:47 +0200 Subject: [PATCH 4/5] Apply suggestions --- .../javascripts/vue_shared/components/empty_result.vue | 6 +++--- app/components/layouts/empty_result_component.haml | 4 ++-- locale/gitlab.pot | 3 +++ .../previews/layouts/empty_result_component_preview.rb | 8 ++++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/vue_shared/components/empty_result.vue b/app/assets/javascripts/vue_shared/components/empty_result.vue index d4ea878856ddfe..ab13b32caeecf3 100644 --- a/app/assets/javascripts/vue_shared/components/empty_result.vue +++ b/app/assets/javascripts/vue_shared/components/empty_result.vue @@ -11,9 +11,9 @@ export const TYPES = { export default { i18n: { titleSearch: __('No results found'), - descriptionSearch: __('Edit your search and try again'), - titleFilter: __('Sorry, your filter produced no results'), - descriptionFilter: __('To widen your search, change or remove filters above'), + descriptionSearch: __('Edit your search and try again.'), + titleFilter: __('No results found'), + descriptionFilter: __('To widen your search, change or remove filters above.'), }, components: { GlEmptyState, diff --git a/app/components/layouts/empty_result_component.haml b/app/components/layouts/empty_result_component.haml index baece68128b0eb..3b86a317614199 100644 --- a/app/components/layouts/empty_result_component.haml +++ b/app/components/layouts/empty_result_component.haml @@ -1,5 +1,5 @@ -- title = filter? ? _('Sorry, your filter produced no results') : _('No results found') -- description = filter? ? _('To widen your search, change or remove filters above') : _('Edit your search and try again') +- title = _('No results found') +- description = filter? ? _('To widen your search, change or remove filters above.') : _('Edit your search and try again.') - svg_path = 'illustrations/empty-state/empty-search-md.svg' = render Pajamas::EmptyStateComponent.new(svg_path: svg_path, diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 11d5e8e02f6655..d865e884c08ec4 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -20466,6 +20466,9 @@ msgstr "" msgid "Edit your search and try again" msgstr "" +msgid "Edit your search and try again." +msgstr "" + msgid "Edit your search filter and try again." msgstr "" diff --git a/spec/components/previews/layouts/empty_result_component_preview.rb b/spec/components/previews/layouts/empty_result_component_preview.rb index de584f77ff5906..52b53cd682c86d 100644 --- a/spec/components/previews/layouts/empty_result_component_preview.rb +++ b/spec/components/previews/layouts/empty_result_component_preview.rb @@ -2,8 +2,12 @@ module Layouts class EmptyResultComponentPreview < ViewComponent::Preview - def default - render(::Layouts::EmptyResultComponent.new) + # @param type select {{ Layouts::EmptyResultComponent::TYPE_OPTIONS }} + + def default(type: :search) + render(::Layouts::EmptyResultComponent.new( + type: type + )) end end end -- GitLab From 0091a57b78b5816c62a68b158f8603a7fa196169 Mon Sep 17 00:00:00 2001 From: Julia Miocene Date: Fri, 6 Sep 2024 12:15:18 +0200 Subject: [PATCH 5/5] Update spec --- spec/components/layouts/empty_result_component_spec.rb | 6 +++--- spec/frontend/vue_shared/components/empty_result_spec.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/components/layouts/empty_result_component_spec.rb b/spec/components/layouts/empty_result_component_spec.rb index cb365dca23b251..4bd7f92de19841 100644 --- a/spec/components/layouts/empty_result_component_spec.rb +++ b/spec/components/layouts/empty_result_component_spec.rb @@ -12,7 +12,7 @@ it 'renders search empty result' do expect(page).to have_css('.gl-empty-state', text: 'No results found') - expect(page).to have_css('.gl-empty-state', text: 'Edit your search and try again') + expect(page).to have_css('.gl-empty-state', text: 'Edit your search and try again.') end it 'renders custom attributes' do @@ -23,8 +23,8 @@ let(:type) { :filter } it 'renders empty result' do - expect(page).to have_css('.gl-empty-state', text: 'Sorry, your filter produced no results') - expect(page).to have_css('.gl-empty-state', text: 'To widen your search, change or remove filters above') + expect(page).to have_css('.gl-empty-state', text: 'No results found') + expect(page).to have_css('.gl-empty-state', text: 'To widen your search, change or remove filters above.') end end end diff --git a/spec/frontend/vue_shared/components/empty_result_spec.js b/spec/frontend/vue_shared/components/empty_result_spec.js index 0879c40e09f8ff..a9e18d7ed4db8c 100644 --- a/spec/frontend/vue_shared/components/empty_result_spec.js +++ b/spec/frontend/vue_shared/components/empty_result_spec.js @@ -20,7 +20,7 @@ describe('Empty result', () => { expect(findEmptyState().props()).toMatchObject({ svgPath: emptyStateSvgPath, title: 'No results found', - description: 'Edit your search and try again', + description: 'Edit your search and try again.', }); }); @@ -29,8 +29,8 @@ describe('Empty result', () => { expect(findEmptyState().props()).toMatchObject({ svgPath: emptyStateSvgPath, - title: 'Sorry, your filter produced no results', - description: 'To widen your search, change or remove filters above', + title: 'No results found', + description: 'To widen your search, change or remove filters above.', }); }); }); -- GitLab