From c5e7ccd29ce41ae569ed09fbcd0d6f35187276a3 Mon Sep 17 00:00:00 2001 From: Jacques Date: Mon, 22 Apr 2024 13:18:56 +0200 Subject: [PATCH 1/5] Add UI components for Beyond Identity check exclusions Added the UI components + tabs for listing the exclusions Changelog: added --- .../components/add_exclusions_drawer.vue | 83 +++++++++++ .../components/exclusions_list.vue | 134 ++++++++++++++++++ .../components/exclusions_list_item.vue | 39 +++++ .../components/exclusions_tabs.vue | 54 +++++++ .../remove_exclusion_confirmation_modal.vue | 58 ++++++++ .../admin/integrations/overrides/index.js | 32 +++++ .../components/list_selector/constants.js | 7 + .../components/list_selector/index.vue | 79 ++++++++--- .../components/list_selector/project_item.vue | 56 ++++++++ app/views/shared/integrations/_tabs.html.haml | 3 +- .../shared/integrations/overrides.html.haml | 6 +- .../beta/beyond_identity_exclusions.yml | 9 ++ locale/gitlab.pot | 36 +++++ .../components/list_selector/index_spec.js | 6 +- 14 files changed, 578 insertions(+), 24 deletions(-) create mode 100644 app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue create mode 100644 app/assets/javascripts/integrations/beyond_identity/components/exclusions_list.vue create mode 100644 app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue create mode 100644 app/assets/javascripts/integrations/beyond_identity/components/exclusions_tabs.vue create mode 100644 app/assets/javascripts/integrations/beyond_identity/components/remove_exclusion_confirmation_modal.vue create mode 100644 app/assets/javascripts/vue_shared/components/list_selector/project_item.vue create mode 100644 config/feature_flags/beta/beyond_identity_exclusions.yml diff --git a/app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue b/app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue new file mode 100644 index 00000000000000..14834912b7dd19 --- /dev/null +++ b/app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue @@ -0,0 +1,83 @@ + + + diff --git a/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list.vue b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list.vue new file mode 100644 index 00000000000000..ec6acbb8676626 --- /dev/null +++ b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list.vue @@ -0,0 +1,134 @@ + + + diff --git a/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue new file mode 100644 index 00000000000000..af995807c2fcb9 --- /dev/null +++ b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue @@ -0,0 +1,39 @@ + + + diff --git a/app/assets/javascripts/integrations/beyond_identity/components/exclusions_tabs.vue b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_tabs.vue new file mode 100644 index 00000000000000..c98b2ced739e86 --- /dev/null +++ b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_tabs.vue @@ -0,0 +1,54 @@ + + + diff --git a/app/assets/javascripts/integrations/beyond_identity/components/remove_exclusion_confirmation_modal.vue b/app/assets/javascripts/integrations/beyond_identity/components/remove_exclusion_confirmation_modal.vue new file mode 100644 index 00000000000000..aacf2f8f2d2137 --- /dev/null +++ b/app/assets/javascripts/integrations/beyond_identity/components/remove_exclusion_confirmation_modal.vue @@ -0,0 +1,58 @@ + + diff --git a/app/assets/javascripts/pages/admin/integrations/overrides/index.js b/app/assets/javascripts/pages/admin/integrations/overrides/index.js index b150470914433f..645f3df79ae7d0 100644 --- a/app/assets/javascripts/pages/admin/integrations/overrides/index.js +++ b/app/assets/javascripts/pages/admin/integrations/overrides/index.js @@ -1,3 +1,35 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; import initIntegrationOverrides from '~/integrations/overrides'; +import ExclusionsList from '~/integrations/beyond_identity/components/exclusions_list.vue'; + +const initBeyondIdentityExclusions = () => { + const el = document.querySelector('.js-vue-beyond-identity-exclusions'); + + if (!el) { + return null; + } + + const { editPath } = el.dataset; + + return new Vue({ + el, + + apolloProvider: new VueApollo({ + defaultClient: createDefaultClient(), + }), + provide: { + editPath, + }, + render(createElement) { + return createElement(ExclusionsList, { + props: {}, + }); + }, + }); +}; + +initBeyondIdentityExclusions(); initIntegrationOverrides(); diff --git a/app/assets/javascripts/vue_shared/components/list_selector/constants.js b/app/assets/javascripts/vue_shared/components/list_selector/constants.js index ad826c6f3e56b0..5ff5d59ef6b6e2 100644 --- a/app/assets/javascripts/vue_shared/components/list_selector/constants.js +++ b/app/assets/javascripts/vue_shared/components/list_selector/constants.js @@ -2,6 +2,7 @@ import { __ } from '~/locale'; import UserItem from './user_item.vue'; import GroupItem from './group_item.vue'; import DeployKeyItem from './deploy_key_item.vue'; +import ProjectItem from './project_item.vue'; export const CONFIG = { users: { @@ -23,4 +24,10 @@ export const CONFIG = { filterKey: 'name', component: DeployKeyItem, }, + projects: { + title: __('Projects'), + icon: 'project', + filterKey: 'id', + component: ProjectItem, + }, }; diff --git a/app/assets/javascripts/vue_shared/components/list_selector/index.vue b/app/assets/javascripts/vue_shared/components/list_selector/index.vue index d79a8d6a00c1c6..67b2e341ce0d26 100644 --- a/app/assets/javascripts/vue_shared/components/list_selector/index.vue +++ b/app/assets/javascripts/vue_shared/components/list_selector/index.vue @@ -1,10 +1,11 @@ + + diff --git a/app/views/shared/integrations/_tabs.html.haml b/app/views/shared/integrations/_tabs.html.haml index 781db59592ea92..bb94590bb9889d 100644 --- a/app/views/shared/integrations/_tabs.html.haml +++ b/app/views/shared/integrations/_tabs.html.haml @@ -1,9 +1,10 @@ +- custom_settings_title = @integration.title == 'Beyond Identity' && Feature.enabled?(:beyond_identity_exclusions) ? s_('Integrations|Exclusions') : s_('Integrations|Projects using custom settings') - if integration.instance_level? .tabs.gl-tabs %div = gl_tabs_nav({ class: 'gl-mb-5' }) do = gl_tab_link_to _('Settings'), scoped_edit_integration_path(integration, project: @project, group: @group) - = gl_tab_link_to s_('Integrations|Projects using custom settings'), scoped_overrides_integration_path(integration) + = gl_tab_link_to custom_settings_title, scoped_overrides_integration_path(integration) = yield diff --git a/app/views/shared/integrations/overrides.html.haml b/app/views/shared/integrations/overrides.html.haml index c25527a605c37f..5d67f63bb2a93d 100644 --- a/app/views/shared/integrations/overrides.html.haml +++ b/app/views/shared/integrations/overrides.html.haml @@ -5,4 +5,8 @@ %h1.page-title.gl-font-size-h-display = @integration.title -.js-vue-integration-overrides{ data: integration_overrides_data(@integration, project: @project, group: @group) } +- if @integration.title == 'Beyond Identity' && Feature.enabled?(:beyond_identity_exclusions) + .js-vue-beyond-identity-exclusions{ data: integration_overrides_data(@integration) } + +- else + .js-vue-integration-overrides{ data: integration_overrides_data(@integration, project: @project, group: @group) } diff --git a/config/feature_flags/beta/beyond_identity_exclusions.yml b/config/feature_flags/beta/beyond_identity_exclusions.yml new file mode 100644 index 00000000000000..e599a4a93c1479 --- /dev/null +++ b/config/feature_flags/beta/beyond_identity_exclusions.yml @@ -0,0 +1,9 @@ +--- +name: beyond_identity_exclusions +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/454372 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/150664 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/457893 +milestone: '17.0' +group: group::source code +type: beta +default_enabled: false diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d1f4bf53cdd508..a4948d6761fbe0 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3094,6 +3094,9 @@ msgstr "" msgid "Add environment" msgstr "" +msgid "Add exclusions" +msgstr "" + msgid "Add existing confidential %{issuableType}" msgstr "" @@ -27416,6 +27419,9 @@ msgstr "" msgid "Integrations|Add an integration" msgstr "" +msgid "Integrations|Add exclusions" +msgstr "" + msgid "Integrations|All details" msgstr "" @@ -27431,6 +27437,9 @@ msgstr "" msgid "Integrations|An error occurred while loading projects using custom settings." msgstr "" +msgid "Integrations|An error occurred while loading projects." +msgstr "" + msgid "Integrations|An event will be triggered when one of the following items happen." msgstr "" @@ -27455,6 +27464,9 @@ msgstr "" msgid "Integrations|Configure the scope of notifications." msgstr "" +msgid "Integrations|Confirm %{type} exclusion removal" +msgstr "" + msgid "Integrations|Connection details" msgstr "" @@ -27500,6 +27512,9 @@ msgstr "" msgid "Integrations|Error: You are trying to upload something other than an allowed file." msgstr "" +msgid "Integrations|Exclusions" +msgstr "" + msgid "Integrations|GitLab administrators can set up integrations that all groups and projects inherit and use by default. These integrations apply to all groups and projects that don't already use custom settings. You can override custom settings for a group or project if the settings are necessary at that level. Learn more about %{integrations_link_start}instance-level integration management%{link_end}." msgstr "" @@ -27545,6 +27560,12 @@ msgstr "" msgid "Integrations|Perform common tasks with slash commands." msgstr "" +msgid "Integrations|Project exclusion removed" +msgstr "" + +msgid "Integrations|Projects included in this list will no longer require commits to be signed." +msgstr "" + msgid "Integrations|Projects using custom settings" msgstr "" @@ -27554,6 +27575,9 @@ msgstr "" msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use parent level defaults." msgstr "" +msgid "Integrations|Remove exclusion" +msgstr "" + msgid "Integrations|Reset integration?" msgstr "" @@ -27593,12 +27617,18 @@ msgstr "" msgid "Integrations|The slash command verification request has expired. Please run the command again." msgstr "" +msgid "Integrations|There are no exclusions" +msgstr "" + msgid "Integrations|There are no projects using custom settings" msgstr "" msgid "Integrations|This integration, and inheriting projects were reset." msgstr "" +msgid "Integrations|This will remove %{name} as an exclusion. Are you sure you want to continue?" +msgstr "" + msgid "Integrations|To keep this project going, create a new issue." msgstr "" @@ -33842,6 +33872,9 @@ msgstr "" msgid "No %{providerTitle} repositories found" msgstr "" +msgid "No %{title} have been added." +msgstr "" + msgid "No Epic" msgstr "" @@ -45592,6 +45625,9 @@ msgstr "" msgid "Search templates" msgstr "" +msgid "Search to add %{title}" +msgstr "" + msgid "Search users" msgstr "" diff --git a/spec/frontend/vue_shared/components/list_selector/index_spec.js b/spec/frontend/vue_shared/components/list_selector/index_spec.js index 6de9a77582cd2a..fafef1060c825c 100644 --- a/spec/frontend/vue_shared/components/list_selector/index_spec.js +++ b/spec/frontend/vue_shared/components/list_selector/index_spec.js @@ -131,7 +131,6 @@ describe('List Selector spec', () => { it('renders a List box component with the correct props', () => { expect(findSearchResultsDropdown().props()).toMatchObject({ - multiple: true, items: searchResponse, }); }); @@ -142,7 +141,7 @@ describe('List Selector spec', () => { it('emits an event when a search result is selected', () => { const firstSearchResult = searchResponse[0]; - findAllUserComponents().at(0).vm.$emit('select', firstSearchResult.username); + findSearchResultsDropdown().vm.$emit('select', firstSearchResult.username); expect(wrapper.emitted('select')).toEqual([ [{ ...firstSearchResult, text: 'Administrator', value: 'root' }], @@ -214,7 +213,6 @@ describe('List Selector spec', () => { it('renders a dropdown for the search results', () => { expect(findSearchResultsDropdown().props()).toMatchObject({ - multiple: true, items: searchResponse, }); }); @@ -225,7 +223,7 @@ describe('List Selector spec', () => { it('emits an event when a search result is selected', () => { const firstSearchResult = searchResponse[0]; - findAllGroupComponents().at(0).vm.$emit('select', firstSearchResult.name); + findSearchResultsDropdown().vm.$emit('select', firstSearchResult.name); expect(wrapper.emitted('select')).toEqual([ [{ ...firstSearchResult, text: 'Flightjs', value: 'Flightjs' }], -- GitLab From 4f589b902929f2d701cf10896285bfa2de686efb Mon Sep 17 00:00:00 2001 From: Jacques Date: Thu, 25 Apr 2024 13:21:10 +0200 Subject: [PATCH 2/5] Add unit tests Added unit tests for the affected components --- .../components/add_exclusions_drawer.vue | 3 +- .../components/exclusions_list.vue | 14 +-- .../components/exclusions_tabs.vue | 17 +-- .../remove_exclusion_confirmation_modal.vue | 2 +- .../admin/integrations/overrides/index.js | 4 +- locale/gitlab.pot | 3 - .../components/add_exclusions_drawer_spec.js | 99 +++++++++++++++ .../components/exclusions_list_item_spec.js | 57 +++++++++ .../components/exclusions_list_spec.js | 113 ++++++++++++++++++ .../components/exclusions_tabs_spec.js | 39 ++++++ .../beyond_identity/components/mock_data.js | 4 + ...emove_exclusion_confirmation_modal_spec.js | 40 +++++++ .../components/list_selector/index_spec.js | 90 ++++++++++++++ .../list_selector/project_item_spec.js | 59 +++++++++ 14 files changed, 510 insertions(+), 34 deletions(-) create mode 100644 spec/frontend/integrations/beyond_identity/components/add_exclusions_drawer_spec.js create mode 100644 spec/frontend/integrations/beyond_identity/components/exclusions_list_item_spec.js create mode 100644 spec/frontend/integrations/beyond_identity/components/exclusions_list_spec.js create mode 100644 spec/frontend/integrations/beyond_identity/components/exclusions_tabs_spec.js create mode 100644 spec/frontend/integrations/beyond_identity/components/mock_data.js create mode 100644 spec/frontend/integrations/beyond_identity/components/remove_exclusion_confirmation_modal_spec.js create mode 100644 spec/frontend/vue_shared/components/list_selector/project_item_spec.js diff --git a/app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue b/app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue index 14834912b7dd19..64bbd0e30e6314 100644 --- a/app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue +++ b/app/assets/javascripts/integrations/beyond_identity/components/add_exclusions_drawer.vue @@ -58,7 +58,7 @@ export default { v-on="$listeners" > diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6e6b68becb6628..6112f55689e11b 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -27560,7 +27560,7 @@ msgstr "" msgid "Integrations|Project exclusion removed" msgstr "" -msgid "Integrations|Projects included in this list will no longer require commits to be signed." +msgid "Integrations|Projects in this list no longer require commits to be signed." msgstr "" msgid "Integrations|Projects using custom settings" @@ -27623,9 +27623,6 @@ msgstr "" msgid "Integrations|This integration, and inheriting projects were reset." msgstr "" -msgid "Integrations|This will remove %{name} as an exclusion. Are you sure you want to continue?" -msgstr "" - msgid "Integrations|To keep this project going, create a new issue." msgstr "" @@ -27650,6 +27647,9 @@ msgstr "" msgid "Integrations|You haven't activated any integrations yet." msgstr "" +msgid "Integrations|You're removing an exclusion for %{name}. Are you sure you want to continue?" +msgstr "" + msgid "Integrations|You've activated every integration 🎉" msgstr "" @@ -42583,6 +42583,9 @@ msgstr "" msgid "Remove epic reference" msgstr "" +msgid "Remove exclusion for %{name}" +msgstr "" + msgid "Remove favicon" msgstr "" diff --git a/spec/frontend/integrations/beyond_identity/components/exclusions_list_spec.js b/spec/frontend/integrations/beyond_identity/components/exclusions_list_spec.js index a6250907d56327..875e9f0a6f546f 100644 --- a/spec/frontend/integrations/beyond_identity/components/exclusions_list_spec.js +++ b/spec/frontend/integrations/beyond_identity/components/exclusions_list_spec.js @@ -35,9 +35,7 @@ describe('ExclusionsList component', () => { it('renders help text', () => { expect( - findByText( - 'Projects included in this list will no longer require commits to be signed.', - ).exists(), + findByText('Projects in this list no longer require commits to be signed.').exists(), ).toBe(true); }); diff --git a/spec/frontend/integrations/beyond_identity/components/remove_exclusion_confirmation_modal_spec.js b/spec/frontend/integrations/beyond_identity/components/remove_exclusion_confirmation_modal_spec.js index fab149838f5a50..92e40fca314c4b 100644 --- a/spec/frontend/integrations/beyond_identity/components/remove_exclusion_confirmation_modal_spec.js +++ b/spec/frontend/integrations/beyond_identity/components/remove_exclusion_confirmation_modal_spec.js @@ -33,7 +33,7 @@ describe('ConfirmRemovalModal component', () => { it('renders body content', () => { expect(findModal().text()).toBe( - 'This will remove Some project as an exclusion. Are you sure you want to continue?', + "You're removing an exclusion for Some project. Are you sure you want to continue?", ); }); }); -- GitLab From bab055f32d708075b6a78a70841fd83b1736e6a8 Mon Sep 17 00:00:00 2001 From: Jacques Date: Fri, 26 Apr 2024 16:25:31 +0200 Subject: [PATCH 4/5] Update unit test Updated the unit test to assert project.id instead of project.name --- .../vue_shared/components/list_selector/project_item_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/frontend/vue_shared/components/list_selector/project_item_spec.js b/spec/frontend/vue_shared/components/list_selector/project_item_spec.js index eeb4e602d74eb9..f0b0b241e5b776 100644 --- a/spec/frontend/vue_shared/components/list_selector/project_item_spec.js +++ b/spec/frontend/vue_shared/components/list_selector/project_item_spec.js @@ -53,7 +53,7 @@ describe('GroupItem spec', () => { it('emits a delete event if the delete button is clicked', () => { findDeleteButton().trigger('click'); - expect(wrapper.emitted('delete')).toEqual([[MOCK_PROJECT.name]]); + expect(wrapper.emitted('delete')).toEqual([[MOCK_PROJECT.id]]); }); }); }); -- GitLab From d373a2b479e6c0b9e51e59ed2eb3763f1724e39d Mon Sep 17 00:00:00 2001 From: Jacques Date: Mon, 29 Apr 2024 10:20:39 +0200 Subject: [PATCH 5/5] Add aria-label to the remove button Added the label to take care of accessibility warning --- .../beyond_identity/components/exclusions_list_item.vue | 9 ++++++++- .../components/exclusions_list_item_spec.js | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue index af995807c2fcb9..e44bf92b7427e4 100644 --- a/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue +++ b/app/assets/javascripts/integrations/beyond_identity/components/exclusions_list_item.vue @@ -1,5 +1,6 @@ @@ -34,6 +36,11 @@ export default { {{ exclusion.name }} - + diff --git a/spec/frontend/integrations/beyond_identity/components/exclusions_list_item_spec.js b/spec/frontend/integrations/beyond_identity/components/exclusions_list_item_spec.js index ca0047cbdaa7ce..1fb9141c98379b 100644 --- a/spec/frontend/integrations/beyond_identity/components/exclusions_list_item_spec.js +++ b/spec/frontend/integrations/beyond_identity/components/exclusions_list_item_spec.js @@ -40,6 +40,8 @@ describe('ExclusionsListItem component', () => { }); it('renders a remove button', () => { + expect(findFindRemoveButton().attributes('aria-label')).toBe('Remove'); + expect(findFindRemoveButton().props()).toMatchObject({ icon: 'remove', category: 'tertiary', -- GitLab