diff --git a/app/graphql/mutations/user_preferences/update.rb b/app/graphql/mutations/user_preferences/update.rb index 111bd2587757e78ad55bbd457249a23b0e959f50..8c4c545aa18291bc9a27012d9494a00efc4da55d 100644 --- a/app/graphql/mutations/user_preferences/update.rb +++ b/app/graphql/mutations/user_preferences/update.rb @@ -6,24 +6,28 @@ class Update < BaseMutation graphql_name 'UserPreferencesUpdate' NON_NULLABLE_ARGS = [ + :extensions_marketplace_opt_in_status, :use_web_ide_extension_marketplace, :visibility_pipeline_id_type ].freeze + argument :extensions_marketplace_opt_in_status, Types::ExtensionsMarketplaceOptInStatusEnum, + required: false, + description: 'Status of the Web IDE Extension Marketplace opt-in for the user.' argument :issues_sort, Types::IssueSortEnum, - required: false, - description: 'Sort order for issue lists.' + required: false, + description: 'Sort order for issue lists.' argument :use_web_ide_extension_marketplace, GraphQL::Types::Boolean, - required: false, - description: 'Whether Web IDE Extension Marketplace is enabled for the user.' + required: false, + description: 'Whether Web IDE Extension Marketplace is enabled for the user.' argument :visibility_pipeline_id_type, Types::VisibilityPipelineIdTypeEnum, - required: false, - description: 'Determines whether the pipeline list shows ID or IID.' + required: false, + description: 'Determines whether the pipeline list shows ID or IID.' field :user_preferences, - Types::UserPreferencesType, - null: true, - description: 'User preferences after mutation.' + Types::UserPreferencesType, + null: true, + description: 'User preferences after mutation.' def resolve(**attributes) attributes.delete_if { |key, value| NON_NULLABLE_ARGS.include?(key) && value.nil? } diff --git a/app/graphql/types/extensions_marketplace_opt_in_status_enum.rb b/app/graphql/types/extensions_marketplace_opt_in_status_enum.rb new file mode 100644 index 0000000000000000000000000000000000000000..4ea4b55a9923d03897350ba1600e61655b7307c9 --- /dev/null +++ b/app/graphql/types/extensions_marketplace_opt_in_status_enum.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +module Types + class ExtensionsMarketplaceOptInStatusEnum < BaseEnum + graphql_name 'ExtensionsMarketplaceOptInStatus' + description 'Values for status of the Web IDE Extension Marketplace opt-in for the user' + + UserPreference.extensions_marketplace_opt_in_statuses.each_key do |field| + value field.upcase, value: field, description: "Web IDE Extension Marketplace opt-in status: #{field.upcase}." + end + end +end diff --git a/app/graphql/types/user_preferences_type.rb b/app/graphql/types/user_preferences_type.rb index e9ac3a28a5303c6a60996bcddcffcba2dd9becce..4d695a6e967cc9e2d616cbff48e63c9f23f66773 100644 --- a/app/graphql/types/user_preferences_type.rb +++ b/app/graphql/types/user_preferences_type.rb @@ -6,6 +6,10 @@ module Types class UserPreferencesType < BaseObject graphql_name 'UserPreferences' + field :extensions_marketplace_opt_in_status, Types::ExtensionsMarketplaceOptInStatusEnum, + description: 'Status of the Web IDE Extension Marketplace opt-in for the user.', + null: false + field :issues_sort, Types::IssueSortEnum, description: 'Sort order for issue lists.', null: true @@ -16,7 +20,8 @@ class UserPreferencesType < BaseObject field :use_web_ide_extension_marketplace, GraphQL::Types::Boolean, description: 'Whether Web IDE Extension Marketplace is enabled for the user.', - null: false + null: false, + deprecated: { reason: 'Use `extensions_marketplace_opt_in_status` instead', milestone: '16.11' } def issues_sort object.issues_sort.to_sym diff --git a/app/models/concerns/enums/web_ide/extensions_marketplace_opt_in_status.rb b/app/models/concerns/enums/web_ide/extensions_marketplace_opt_in_status.rb new file mode 100644 index 0000000000000000000000000000000000000000..44e63dcaa27f7baaac8916fc80f2a5ab7ff3e355 --- /dev/null +++ b/app/models/concerns/enums/web_ide/extensions_marketplace_opt_in_status.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Enums + module WebIde + module ExtensionsMarketplaceOptInStatus + def self.statuses + { unset: 0, enabled: 1, disabled: 2 } + end + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 35b0a73049ee74c9a978528a87906b150799ef6c..acda8cd88e741bc779619477a11ac9b50f4572f7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -408,6 +408,7 @@ def update_tracked_fields!(request) :sourcegraph_enabled, :sourcegraph_enabled=, :gitpod_enabled, :gitpod_enabled=, :use_web_ide_extension_marketplace, :use_web_ide_extension_marketplace=, + :extensions_marketplace_opt_in_status, :extensions_marketplace_opt_in_status=, :setup_for_company, :setup_for_company=, :project_shortcut_buttons, :project_shortcut_buttons=, :keyboard_shortcuts_enabled, :keyboard_shortcuts_enabled=, diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb index caedf08fa44a52e7a96b0882aac78268cd42241a..19a7601be32783d02b083a6e8b695194737831dd 100644 --- a/app/models/user_preference.rb +++ b/app/models/user_preference.rb @@ -42,6 +42,7 @@ class UserPreference < MainClusterwide::ApplicationRecord attribute :use_web_ide_extension_marketplace, default: false enum visibility_pipeline_id_type: { id: 0, iid: 1 } + enum extensions_marketplace_opt_in_status: Enums::WebIde::ExtensionsMarketplaceOptInStatus.statuses class << self def notes_filters diff --git a/db/migrate/20240410000000_add_extensions_marketplace_opt_in_status_to_user_preferences.rb b/db/migrate/20240410000000_add_extensions_marketplace_opt_in_status_to_user_preferences.rb new file mode 100644 index 0000000000000000000000000000000000000000..d81193d2a5da89eb3516da496c04309af3b06cfe --- /dev/null +++ b/db/migrate/20240410000000_add_extensions_marketplace_opt_in_status_to_user_preferences.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddExtensionsMarketplaceOptInStatusToUserPreferences < Gitlab::Database::Migration[2.2] + milestone '16.11' + + def change + add_column :user_preferences, :extensions_marketplace_opt_in_status, :smallint, default: 0, null: false + end +end diff --git a/db/schema_migrations/20240410000000 b/db/schema_migrations/20240410000000 new file mode 100644 index 0000000000000000000000000000000000000000..48b31e3a3bcf3ba828ac2d63f709f69b86b2557e --- /dev/null +++ b/db/schema_migrations/20240410000000 @@ -0,0 +1 @@ +2f045332b7600514f8adeea441afca3c5cd8eddd5a7fab261e48fc373046ead1 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index b5a3dc574b0ef50c5ad19c7bcf16561d99d6954d..b983ebe6d448f81a0efa5c5bf6ca253f935414fc 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -17109,6 +17109,7 @@ CREATE TABLE user_preferences ( time_display_format smallint DEFAULT 0 NOT NULL, home_organization_id bigint, use_web_ide_extension_marketplace boolean DEFAULT false NOT NULL, + extensions_marketplace_opt_in_status smallint DEFAULT 0 NOT NULL, CONSTRAINT check_1d670edc68 CHECK ((time_display_relative IS NOT NULL)), CONSTRAINT check_89bf269f41 CHECK ((char_length(diffs_deletion_color) <= 7)), CONSTRAINT check_b22446f91a CHECK ((render_whitespace_in_code IS NOT NULL)), diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 8d7b5069dea77cbd2974dab769c5e1ee2f4f9ffd..8b880d584deffefed82fc109b1b3eb18d19a31c7 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -8953,6 +8953,7 @@ Input type: `UserPreferencesUpdateInput` | Name | Type | Description | | ---- | ---- | ----------- | | <a id="mutationuserpreferencesupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationuserpreferencesupdateextensionsmarketplaceoptinstatus"></a>`extensionsMarketplaceOptInStatus` | [`ExtensionsMarketplaceOptInStatus`](#extensionsmarketplaceoptinstatus) | Status of the Web IDE Extension Marketplace opt-in for the user. | | <a id="mutationuserpreferencesupdateissuessort"></a>`issuesSort` | [`IssueSort`](#issuesort) | Sort order for issue lists. | | <a id="mutationuserpreferencesupdateusewebideextensionmarketplace"></a>`useWebIdeExtensionMarketplace` | [`Boolean`](#boolean) | Whether Web IDE Extension Marketplace is enabled for the user. | | <a id="mutationuserpreferencesupdatevisibilitypipelineidtype"></a>`visibilityPipelineIdType` | [`VisibilityPipelineIdType`](#visibilitypipelineidtype) | Determines whether the pipeline list shows ID or IID. | @@ -30228,8 +30229,9 @@ fields relate to interactions between the two entities. | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="userpreferencesextensionsmarketplaceoptinstatus"></a>`extensionsMarketplaceOptInStatus` | [`ExtensionsMarketplaceOptInStatus!`](#extensionsmarketplaceoptinstatus) | Status of the Web IDE Extension Marketplace opt-in for the user. | | <a id="userpreferencesissuessort"></a>`issuesSort` | [`IssueSort`](#issuesort) | Sort order for issue lists. | -| <a id="userpreferencesusewebideextensionmarketplace"></a>`useWebIdeExtensionMarketplace` | [`Boolean!`](#boolean) | Whether Web IDE Extension Marketplace is enabled for the user. | +| <a id="userpreferencesusewebideextensionmarketplace"></a>`useWebIdeExtensionMarketplace` **{warning-solid}** | [`Boolean!`](#boolean) | **Deprecated** in GitLab 16.11. Use `extensions_marketplace_opt_in_status` instead. | | <a id="userpreferencesvisibilitypipelineidtype"></a>`visibilityPipelineIdType` | [`VisibilityPipelineIdType`](#visibilitypipelineidtype) | Determines whether the pipeline list shows ID or IID. | ### `UserStatus` @@ -32671,6 +32673,16 @@ Event action. | <a id="eventactionreopened"></a>`REOPENED` | Reopened action. | | <a id="eventactionupdated"></a>`UPDATED` | Updated action. | +### `ExtensionsMarketplaceOptInStatus` + +Values for status of the Web IDE Extension Marketplace opt-in for the user. + +| Value | Description | +| ----- | ----------- | +| <a id="extensionsmarketplaceoptinstatusdisabled"></a>`DISABLED` | Web IDE Extension Marketplace opt-in status: DISABLED. | +| <a id="extensionsmarketplaceoptinstatusenabled"></a>`ENABLED` | Web IDE Extension Marketplace opt-in status: ENABLED. | +| <a id="extensionsmarketplaceoptinstatusunset"></a>`UNSET` | Web IDE Extension Marketplace opt-in status: UNSET. | + ### `FindingReportsComparerStatus` Report comparison status. diff --git a/spec/graphql/types/extensions_marketplace_opt_in_status_enum_spec.rb b/spec/graphql/types/extensions_marketplace_opt_in_status_enum_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..84199f443b21e6a99640a5899e95f81ee1a03102 --- /dev/null +++ b/spec/graphql/types/extensions_marketplace_opt_in_status_enum_spec.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Types::ExtensionsMarketplaceOptInStatusEnum, feature_category: :web_ide do + specify { expect(described_class.graphql_name).to eq('ExtensionsMarketplaceOptInStatus') } + + it 'exposes all the existing extensions_marketplace_opt_in_status values' do + expect(described_class.values.keys).to contain_exactly('UNSET', 'ENABLED', 'DISABLED') + end +end diff --git a/spec/graphql/types/user_preferences_type_spec.rb b/spec/graphql/types/user_preferences_type_spec.rb index 87fac17a5ba6b7d21457950f8645009716152b18..1db51d27b221dd9abc891a93cb513405d4dffada 100644 --- a/spec/graphql/types/user_preferences_type_spec.rb +++ b/spec/graphql/types/user_preferences_type_spec.rb @@ -10,6 +10,7 @@ issues_sort visibility_pipeline_id_type use_web_ide_extension_marketplace + extensions_marketplace_opt_in_status ] expect(described_class).to have_graphql_fields(*expected_fields) diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb index 8852c14c1aadb3cb3795b09edbee4310e5d6a2fb..efcd1b620e1bc1bb38d3adb32c87b6a0358e2590 100644 --- a/spec/models/user_preference_spec.rb +++ b/spec/models/user_preference_spec.rb @@ -73,6 +73,19 @@ it { is_expected.to define_enum_for(:visibility_pipeline_id_type).with_values(id: 0, iid: 1) } end + describe 'extensions_marketplace_opt_in_status' do + it 'is set to 0 by default' do + pref = described_class.new + + expect(pref.extensions_marketplace_opt_in_status).to eq('unset') + end + + it do + is_expected + .to define_enum_for(:extensions_marketplace_opt_in_status).with_values(unset: 0, enabled: 1, disabled: 2) + end + end + describe 'user belongs to the home organization' do let_it_be(:organization) { create(:organization) } diff --git a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb index b1cd3259eebe8ffab06e127dde36ccaf61ad45af..63a3a48fbd60deafff8d3951526b92ddd9061462 100644 --- a/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb +++ b/spec/requests/api/graphql/mutations/user_preferences/update_spec.rb @@ -11,6 +11,7 @@ let(:input) do { + 'extensionsMarketplaceOptInStatus' => 'ENABLED', 'issuesSort' => sort_value, 'visibilityPipelineIdType' => 'IID', 'useWebIdeExtensionMarketplace' => true @@ -25,11 +26,13 @@ post_graphql_mutation(mutation, current_user: current_user) expect(response).to have_gitlab_http_status(:success) + expect(mutation_response['userPreferences']['extensionsMarketplaceOptInStatus']).to eq('ENABLED') expect(mutation_response['userPreferences']['issuesSort']).to eq(sort_value) expect(mutation_response['userPreferences']['visibilityPipelineIdType']).to eq('IID') expect(mutation_response['userPreferences']['useWebIdeExtensionMarketplace']).to eq(true) expect(current_user.user_preference.persisted?).to eq(true) + expect(current_user.user_preference.extensions_marketplace_opt_in_status).to eq('enabled') expect(current_user.user_preference.issues_sort).to eq(Types::IssueSortEnum.values[sort_value].value.to_s) expect(current_user.user_preference.visibility_pipeline_id_type).to eq('iid') expect(current_user.user_preference.use_web_ide_extension_marketplace).to eq(true) @@ -39,6 +42,7 @@ context 'when user has existing preference' do let(:init_user_preference) do { + extensions_marketplace_opt_in_status: 'enabled', issues_sort: Types::IssueSortEnum.values['TITLE_DESC'].value, visibility_pipeline_id_type: 'id', use_web_ide_extension_marketplace: true @@ -65,6 +69,7 @@ context 'when input has nil attributes' do let(:input) do { + 'extensionsMarketplaceOptInStatus' => nil, 'issuesSort' => nil, 'visibilityPipelineIdType' => nil, 'useWebIdeExtensionMarketplace' => nil @@ -80,6 +85,7 @@ # These are nullable and are exepcted to change issues_sort: nil, # These should not have changed + extensions_marketplace_opt_in_status: init_user_preference[:extensions_marketplace_opt_in_status], visibility_pipeline_id_type: init_user_preference[:visibility_pipeline_id_type], use_web_ide_extension_marketplace: init_user_preference[:use_web_ide_extension_marketplace] })