From 9635a60a492740414de7c4b7583c645cabfaa109 Mon Sep 17 00:00:00 2001 From: Nick Leonard Date: Fri, 12 Dec 2025 16:14:04 -0600 Subject: [PATCH 1/2] Adds type scope for boards Allows one or more types to be set as a board scope, using existing scope patterns. Changelog: added --- .../boards/components/board_form.vue | 7 +- .../boards/board_issue_input_base_type.rb | 4 + ...212041921_add_work_item_types_to_boards.rb | 9 ++ db/structure.sql | 1 + doc/api/graphql/reference/_index.md | 7 + .../assets/javascripts/boards/boards_util.js | 13 ++ .../components/board_filtered_search.vue | 1 + .../boards/components/board_form.vue | 1 + .../boards/components/board_scope.vue | 8 + .../components/work_item_type_select.vue | 153 ++++++++++++++++++ .../graphql/board_scope.fragment.graphql | 1 + .../ee/resolvers/board_item_filterable.rb | 7 + ee/app/graphql/ee/types/board_type.rb | 3 + .../mutations/boards/scoped_board_mutation.rb | 4 + ee/app/models/ee/board.rb | 3 +- ee/app/services/ee/boards/update_service.rb | 3 +- locale/gitlab.pot | 9 ++ 17 files changed, 231 insertions(+), 3 deletions(-) create mode 100644 db/migrate/20251212041921_add_work_item_types_to_boards.rb create mode 100644 ee/app/assets/javascripts/boards/components/work_item_type_select.vue diff --git a/app/assets/javascripts/boards/components/board_form.vue b/app/assets/javascripts/boards/components/board_form.vue index c8abf8ee4aae44..d264cb3907d5e1 100644 --- a/app/assets/javascripts/boards/components/board_form.vue +++ b/app/assets/javascripts/boards/components/board_form.vue @@ -21,6 +21,7 @@ const boardDefaults = { iteration: {}, assignee: {}, weight: null, + workItemTypes: [], hideBacklogList: false, hideClosedList: false, }; @@ -273,12 +274,12 @@ export default { } else { this.$emit('addBoard', board); } + this.isDisabled = true; this.close(); } catch (error) { setError({ error, message: this.$options.i18n.saveErrorMessage }); } finally { this.isLoading = false; - this.isDisabled = true; } } }, @@ -325,6 +326,9 @@ export default { weight, }; }, + setWorkItemTypes(types) { + this.board.workItemTypes = types.map((type) => type.id); + }, }, formType, }; @@ -396,6 +400,7 @@ export default { @set-assignee="setAssignee" @set-milestone="setMilestone" @set-weight="setWeight" + @set-work-item-types="setWorkItemTypes" /> diff --git a/ee/app/assets/javascripts/boards/components/work_item_type_select.vue b/ee/app/assets/javascripts/boards/components/work_item_type_select.vue new file mode 100644 index 00000000000000..ab90d77335a9cb --- /dev/null +++ b/ee/app/assets/javascripts/boards/components/work_item_type_select.vue @@ -0,0 +1,153 @@ + + + diff --git a/ee/app/assets/javascripts/boards/graphql/board_scope.fragment.graphql b/ee/app/assets/javascripts/boards/graphql/board_scope.fragment.graphql index 1bbe56426fb016..f55cbe170095ad 100644 --- a/ee/app/assets/javascripts/boards/graphql/board_scope.fragment.graphql +++ b/ee/app/assets/javascripts/boards/graphql/board_scope.fragment.graphql @@ -28,4 +28,5 @@ fragment BoardScopeFragment on Board { durationInWeeks } weight + workItemTypes } diff --git a/ee/app/graphql/ee/resolvers/board_item_filterable.rb b/ee/app/graphql/ee/resolvers/board_item_filterable.rb index af1701e5b2e431..f64d8c7fb8720a 100644 --- a/ee/app/graphql/ee/resolvers/board_item_filterable.rb +++ b/ee/app/graphql/ee/resolvers/board_item_filterable.rb @@ -12,6 +12,7 @@ def set_filter_values(filters) filter_by_iteration(filters) filter_by_iteration_cadence(filters) filter_by_weight(filters) + filter_by_work_item_types(filters) super end @@ -71,6 +72,12 @@ def filter_by_weight(filters) filters[:weight] = weight_wildcard if weight_wildcard end + + def filter_by_work_item_types(filters) + return if filters[:work_item_types].blank? + + filters[:work_item_types] = filters[:work_item_types].map(&:upcase) + end end end end diff --git a/ee/app/graphql/ee/types/board_type.rb b/ee/app/graphql/ee/types/board_type.rb index 795865143b8dc5..dbd6130c7e43d8 100644 --- a/ee/app/graphql/ee/types/board_type.rb +++ b/ee/app/graphql/ee/types/board_type.rb @@ -27,6 +27,9 @@ module BoardType description: 'Board iteration cadence.' field :weight, type: GraphQL::Types::Int, null: true, description: 'Weight of the board.' + + field :work_item_types, [GraphQL::Types::String], null: true, + description: 'Work item types to filter by on the board.' end end end diff --git a/ee/app/graphql/mutations/boards/scoped_board_mutation.rb b/ee/app/graphql/mutations/boards/scoped_board_mutation.rb index 11c00ec87e59f9..3ac260014612c0 100644 --- a/ee/app/graphql/mutations/boards/scoped_board_mutation.rb +++ b/ee/app/graphql/mutations/boards/scoped_board_mutation.rb @@ -14,6 +14,10 @@ module ScopedBoardMutation required: false, description: 'IDs of labels to be added to the board.' + argument :work_item_types, [GraphQL::Types::String], + required: false, + description: 'Work item types to filter by on the board.' + validates mutually_exclusive: [:labels, :label_ids] end diff --git a/ee/app/models/ee/board.rb b/ee/app/models/ee/board.rb index 38ff71ec5f1cad..3f6a5fa618a2c4 100644 --- a/ee/app/models/ee/board.rb +++ b/ee/app/models/ee/board.rb @@ -37,7 +37,8 @@ def scoped? EMPTY_SCOPE_STATE.exclude?(milestone_id) || EMPTY_SCOPE_STATE.exclude?(weight) || labels.any? || - assignee.present? + assignee.present? || + work_item_types.any? end def milestone diff --git a/ee/app/services/ee/boards/update_service.rb b/ee/app/services/ee/boards/update_service.rb index 8b5aaaac4b4058..c92a0d94c0111c 100644 --- a/ee/app/services/ee/boards/update_service.rb +++ b/ee/app/services/ee/boards/update_service.rb @@ -20,7 +20,8 @@ def permitted_params permitted = super if parent.feature_available?(:scoped_issue_board) - permitted += %i[milestone_id iteration_id iteration_cadence_id assignee_id weight labels label_ids] + permitted += %i[milestone_id iteration_id iteration_cadence_id assignee_id weight labels label_ids + work_item_types] end permitted diff --git a/locale/gitlab.pot b/locale/gitlab.pot index de441c898f70f4..580a6bae6d8dc2 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -11701,12 +11701,18 @@ msgstr "" msgid "BoardScope|Any label" msgstr "" +msgid "BoardScope|Any type" +msgstr "" + msgid "BoardScope|Assignee" msgstr "" msgid "BoardScope|Choose labels" msgstr "" +msgid "BoardScope|Choose types" +msgstr "" + msgid "BoardScope|Current iteration" msgstr "" @@ -11752,6 +11758,9 @@ msgstr "" msgid "BoardScope|Started" msgstr "" +msgid "BoardScope|Type" +msgstr "" + msgid "BoardScope|Upcoming" msgstr "" -- GitLab From 194149dce283c70d601836a420d368d507220db7 Mon Sep 17 00:00:00 2001 From: Nick Leonard Date: Fri, 12 Dec 2025 16:41:05 -0600 Subject: [PATCH 2/2] Remove from epic boards --- .../javascripts/boards/components/board_scope.vue | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ee/app/assets/javascripts/boards/components/board_scope.vue b/ee/app/assets/javascripts/boards/components/board_scope.vue index 77d4f2c72a2db1..d8966c12a732e4 100644 --- a/ee/app/assets/javascripts/boards/components/board_scope.vue +++ b/ee/app/assets/javascripts/boards/components/board_scope.vue @@ -81,6 +81,13 @@ export default { {{ scopeText }}

+ + - -
-- GitLab