Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
2e5179b0
Commit
2e5179b0
authored
Aug 10, 2020
by
Felipe Artur
Committed by
Douglas Barbosa Alexandre
Aug 10, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add mutation to update boards
Allow to update boards via GraphQL
parent
dcea86d0
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
507 additions
and
4 deletions
+507
-4
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+87
-1
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+246
-1
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+15
-1
ee/app/graphql/ee/types/board_type.rb
ee/app/graphql/ee/types/board_type.rb
+13
-1
ee/app/graphql/ee/types/mutation_type.rb
ee/app/graphql/ee/types/mutation_type.rb
+1
-0
ee/app/graphql/mutations/boards/update.rb
ee/app/graphql/mutations/boards/update.rb
+83
-0
ee/changelogs/unreleased/issue_218031_be_add_mutation.yml
ee/changelogs/unreleased/issue_218031_be_add_mutation.yml
+5
-0
ee/spec/graphql/mutations/boards/update_spec.rb
ee/spec/graphql/mutations/boards/update_spec.rb
+57
-0
No files found.
doc/api/graphql/reference/gitlab_schema.graphql
View file @
2e5179b0
...
@@ -992,6 +992,21 @@ enum BlobViewersType {
...
@@ -992,6 +992,21 @@ enum BlobViewersType {
Represents a project or group board
Represents a project or group board
"""
"""
type
Board
{
type
Board
{
"""
The
board
assignee
.
"""
assignee
:
User
"""
Whether
or
not
backlog
list
is
hidden
.
"""
hideBacklogList
:
Boolean
"""
Whether
or
not
closed
list
is
hidden
.
"""
hideClosedList
:
Boolean
"""
"""
ID
(
global
ID
)
of
the
board
ID
(
global
ID
)
of
the
board
"""
"""
...
@@ -1027,13 +1042,18 @@ type Board {
...
@@ -1027,13 +1042,18 @@ type Board {
last
:
Int
last
:
Int
):
BoardListConnection
):
BoardListConnection
"""
The
board
milestone
.
"""
milestone
:
Milestone
"""
"""
Name
of
the
board
Name
of
the
board
"""
"""
name
:
String
name
:
String
"""
"""
Weight
of
the
board
Weight
of
the
board
.
"""
"""
weight
:
Int
weight
:
Int
}
}
...
@@ -9075,6 +9095,7 @@ type Mutation {
...
@@ -9075,6 +9095,7 @@ type Mutation {
todosMarkAllDone
(
input
:
TodosMarkAllDoneInput
!):
TodosMarkAllDonePayload
todosMarkAllDone
(
input
:
TodosMarkAllDoneInput
!):
TodosMarkAllDonePayload
toggleAwardEmoji
(
input
:
ToggleAwardEmojiInput
!):
ToggleAwardEmojiPayload
@
deprecated
(
reason
:
"
Use
awardEmojiToggle
.
Deprecated
in
13.2"
)
toggleAwardEmoji
(
input
:
ToggleAwardEmojiInput
!):
ToggleAwardEmojiPayload
@
deprecated
(
reason
:
"
Use
awardEmojiToggle
.
Deprecated
in
13.2"
)
updateAlertStatus
(
input
:
UpdateAlertStatusInput
!):
UpdateAlertStatusPayload
updateAlertStatus
(
input
:
UpdateAlertStatusInput
!):
UpdateAlertStatusPayload
updateBoard
(
input
:
UpdateBoardInput
!):
UpdateBoardPayload
updateContainerExpirationPolicy
(
input
:
UpdateContainerExpirationPolicyInput
!):
UpdateContainerExpirationPolicyPayload
updateContainerExpirationPolicy
(
input
:
UpdateContainerExpirationPolicyInput
!):
UpdateContainerExpirationPolicyPayload
updateEpic
(
input
:
UpdateEpicInput
!):
UpdateEpicPayload
updateEpic
(
input
:
UpdateEpicInput
!):
UpdateEpicPayload
...
@@ -14892,6 +14913,71 @@ type UpdateAlertStatusPayload {
...
@@ -14892,6 +14913,71 @@ type UpdateAlertStatusPayload {
todo
:
Todo
todo
:
Todo
}
}
"""
Autogenerated input type of UpdateBoard
"""
input
UpdateBoardInput
{
"""
The
id
of
user
to
be
assigned
to
the
board
.
"""
assigneeId
:
ID
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Whether
or
not
backlog
list
is
hidden
.
"""
hideBacklogList
:
Boolean
"""
Whether
or
not
closed
list
is
hidden
.
"""
hideClosedList
:
Boolean
"""
The
board
global
id
.
"""
id
:
ID
!
"""
The
id
of
milestone
to
be
assigned
to
the
board
.
"""
milestoneId
:
ID
"""
Name
of
the
board
"""
name
:
String
"""
The
weight
value
to
be
assigned
to
the
board
.
"""
weight
:
Int
}
"""
Autogenerated return type of UpdateBoard
"""
type
UpdateBoardPayload
{
"""
The
board
after
mutation
.
"""
board
:
Board
"""
A
unique
identifier
for
the
client
performing
the
mutation
.
"""
clientMutationId
:
String
"""
Errors
encountered
during
execution
of
the
mutation
.
"""
errors
:
[
String
!]!
}
"""
"""
Autogenerated input type of UpdateContainerExpirationPolicy
Autogenerated input type of UpdateContainerExpirationPolicy
"""
"""
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
2e5179b0
...
@@ -2661,6 +2661,48 @@
...
@@ -2661,6 +2661,48 @@
"name": "Board",
"name": "Board",
"description": "Represents a project or group board",
"description": "Represents a project or group board",
"fields": [
"fields": [
{
"name": "assignee",
"description": "The board assignee.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "User",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "hideBacklogList",
"description": "Whether or not backlog list is hidden.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "hideClosedList",
"description": "Whether or not closed list is hidden.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
{
"name": "id",
"name": "id",
"description": "ID (global ID) of the board",
"description": "ID (global ID) of the board",
...
@@ -2742,6 +2784,20 @@
...
@@ -2742,6 +2784,20 @@
"isDeprecated": false,
"isDeprecated": false,
"deprecationReason": null
"deprecationReason": null
},
},
{
"name": "milestone",
"description": "The board milestone.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Milestone",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
{
"name": "name",
"name": "name",
"description": "Name of the board",
"description": "Name of the board",
...
@@ -2758,7 +2814,7 @@
...
@@ -2758,7 +2814,7 @@
},
},
{
{
"name": "weight",
"name": "weight",
"description": "Weight of the board",
"description": "Weight of the board
.
",
"args": [
"args": [
],
],
...
@@ -27030,6 +27086,33 @@
...
@@ -27030,6 +27086,33 @@
"isDeprecated": false,
"isDeprecated": false,
"deprecationReason": null
"deprecationReason": null
},
},
{
"name": "updateBoard",
"description": null,
"args": [
{
"name": "input",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "INPUT_OBJECT",
"name": "UpdateBoardInput",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "UpdateBoardPayload",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
{
"name": "updateContainerExpirationPolicy",
"name": "updateContainerExpirationPolicy",
"description": null,
"description": null,
...
@@ -44014,6 +44097,168 @@
...
@@ -44014,6 +44097,168 @@
"enumValues": null,
"enumValues": null,
"possibleTypes": null
"possibleTypes": null
},
},
{
"kind": "INPUT_OBJECT",
"name": "UpdateBoardInput",
"description": "Autogenerated input type of UpdateBoard",
"fields": null,
"inputFields": [
{
"name": "id",
"description": "The board global id.",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
},
"defaultValue": null
},
{
"name": "name",
"description": "Name of the board",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
},
{
"name": "hideBacklogList",
"description": "Whether or not backlog list is hidden.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": null
},
{
"name": "hideClosedList",
"description": "Whether or not closed list is hidden.",
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"defaultValue": null
},
{
"name": "assigneeId",
"description": "The id of user to be assigned to the board.",
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"defaultValue": null
},
{
"name": "milestoneId",
"description": "The id of milestone to be assigned to the board.",
"type": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
},
"defaultValue": null
},
{
"name": "weight",
"description": "The weight value to be assigned to the board.",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null
}
],
"interfaces": null,
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "UpdateBoardPayload",
"description": "Autogenerated return type of UpdateBoard",
"fields": [
{
"name": "board",
"description": "The board after mutation.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "Board",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "clientMutationId",
"description": "A unique identifier for the client performing the mutation.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "errors",
"description": "Errors encountered during execution of the mutation.",
"args": [
],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
}
}
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
{
"kind": "INPUT_OBJECT",
"kind": "INPUT_OBJECT",
"name": "UpdateContainerExpirationPolicyInput",
"name": "UpdateContainerExpirationPolicyInput",
doc/api/graphql/reference/index.md
View file @
2e5179b0
...
@@ -188,9 +188,13 @@ Represents a project or group board
...
@@ -188,9 +188,13 @@ Represents a project or group board
| Name | Type | Description |
| Name | Type | Description |
| --- | ---- | ---------- |
| --- | ---- | ---------- |
|
`assignee`
| User | The board assignee. |
|
`hideBacklogList`
| Boolean | Whether or not backlog list is hidden. |
|
`hideClosedList`
| Boolean | Whether or not closed list is hidden. |
|
`id`
| ID! | ID (global ID) of the board |
|
`id`
| ID! | ID (global ID) of the board |
|
`milestone`
| Milestone | The board milestone. |
|
`name`
| String | Name of the board |
|
`name`
| String | Name of the board |
|
`weight`
| Int | Weight of the board |
|
`weight`
| Int | Weight of the board
.
|
## BoardList
## BoardList
...
@@ -2236,6 +2240,16 @@ Autogenerated return type of UpdateAlertStatus
...
@@ -2236,6 +2240,16 @@ Autogenerated return type of UpdateAlertStatus
|
`issue`
| Issue | The issue created after mutation |
|
`issue`
| Issue | The issue created after mutation |
|
`todo`
| Todo | The todo after mutation |
|
`todo`
| Todo | The todo after mutation |
## UpdateBoardPayload
Autogenerated return type of UpdateBoard
| Name | Type | Description |
| --- | ---- | ---------- |
|
`board`
| Board | The board after mutation. |
|
`clientMutationId`
| String | A unique identifier for the client performing the mutation. |
|
`errors`
| String! => Array | Errors encountered during execution of the mutation. |
## UpdateContainerExpirationPolicyPayload
## UpdateContainerExpirationPolicyPayload
Autogenerated return type of UpdateContainerExpirationPolicy
Autogenerated return type of UpdateContainerExpirationPolicy
...
...
ee/app/graphql/ee/types/board_type.rb
View file @
2e5179b0
...
@@ -6,8 +6,20 @@ module EE
...
@@ -6,8 +6,20 @@ module EE
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
prepended
do
prepended
do
field
:assignee
,
type:
::
Types
::
UserType
,
null:
true
,
description:
'The board assignee.'
field
:milestone
,
type:
::
Types
::
MilestoneType
,
null:
true
,
description:
'The board milestone.'
field
:hide_backlog_list
,
type:
GraphQL
::
BOOLEAN_TYPE
,
null:
true
,
description:
'Whether or not backlog list is hidden.'
field
:hide_closed_list
,
type:
GraphQL
::
BOOLEAN_TYPE
,
null:
true
,
description:
'Whether or not closed list is hidden.'
field
:weight
,
type:
GraphQL
::
INT_TYPE
,
null:
true
,
field
:weight
,
type:
GraphQL
::
INT_TYPE
,
null:
true
,
description:
'Weight of the board'
description:
'Weight of the board
.
'
end
end
end
end
end
end
...
...
ee/app/graphql/ee/types/mutation_type.rb
View file @
2e5179b0
...
@@ -19,6 +19,7 @@ module EE
...
@@ -19,6 +19,7 @@ module EE
mount_mutation
::
Mutations
::
RequirementsManagement
::
CreateRequirement
mount_mutation
::
Mutations
::
RequirementsManagement
::
CreateRequirement
mount_mutation
::
Mutations
::
RequirementsManagement
::
UpdateRequirement
mount_mutation
::
Mutations
::
RequirementsManagement
::
UpdateRequirement
mount_mutation
::
Mutations
::
Vulnerabilities
::
Dismiss
mount_mutation
::
Mutations
::
Vulnerabilities
::
Dismiss
mount_mutation
::
Mutations
::
Boards
::
Update
mount_mutation
::
Mutations
::
Boards
::
Lists
::
UpdateLimitMetrics
mount_mutation
::
Mutations
::
Boards
::
Lists
::
UpdateLimitMetrics
mount_mutation
::
Mutations
::
InstanceSecurityDashboard
::
AddProject
mount_mutation
::
Mutations
::
InstanceSecurityDashboard
::
AddProject
mount_mutation
::
Mutations
::
InstanceSecurityDashboard
::
RemoveProject
mount_mutation
::
Mutations
::
InstanceSecurityDashboard
::
RemoveProject
...
...
ee/app/graphql/mutations/boards/update.rb
0 → 100644
View file @
2e5179b0
# frozen_string_literal: true
module
Mutations
module
Boards
class
Update
<
::
Mutations
::
BaseMutation
graphql_name
'UpdateBoard'
argument
:id
,
GraphQL
::
ID_TYPE
,
required:
true
,
description:
'The board global id.'
argument
:name
,
GraphQL
::
STRING_TYPE
,
required:
false
,
description:
copy_field_description
(
Types
::
BoardType
,
:name
)
argument
:hide_backlog_list
,
GraphQL
::
BOOLEAN_TYPE
,
required:
false
,
description:
copy_field_description
(
Types
::
BoardType
,
:hide_backlog_list
)
argument
:hide_closed_list
,
GraphQL
::
BOOLEAN_TYPE
,
required:
false
,
description:
copy_field_description
(
Types
::
BoardType
,
:hide_closed_list
)
argument
:assignee_id
,
GraphQL
::
ID_TYPE
,
required:
false
,
loads:
::
Types
::
UserType
,
description:
'The id of user to be assigned to the board.'
argument
:milestone_id
,
GraphQL
::
ID_TYPE
,
required:
false
,
description:
'The id of milestone to be assigned to the board.'
argument
:weight
,
GraphQL
::
INT_TYPE
,
required:
false
,
description:
'The weight value to be assigned to the board.'
field
:board
,
Types
::
BoardType
,
null:
true
,
description:
"The board after mutation."
authorize
:admin_board
def
resolve
(
id
:,
assignee:
nil
,
**
args
)
board
=
authorized_find!
(
id:
id
)
parsed_params
=
parse_arguments
(
args
)
::
Boards
::
UpdateService
.
new
(
board
.
resource_parent
,
current_user
,
parsed_params
).
execute
(
board
)
{
board:
board
,
errors:
errors_on_object
(
board
)
}
end
private
def
find_object
(
id
:)
GitlabSchema
.
object_from_id
(
id
)
end
def
parse_arguments
(
args
=
{})
if
args
[
:assignee_id
]
args
[
:assignee_id
]
=
GitlabSchema
.
parse_gid
(
args
[
:assignee_id
],
expected_type:
::
User
).
model_id
end
if
args
[
:milestone_id
]
args
[
:milestone_id
]
=
GitlabSchema
.
parse_gid
(
args
[
:milestone_id
],
expected_type:
::
Milestone
).
model_id
end
args
end
end
end
end
ee/changelogs/unreleased/issue_218031_be_add_mutation.yml
0 → 100644
View file @
2e5179b0
---
title
:
Add ability to update issue board configuration options using GraphQL
merge_request
:
38413
author
:
type
:
added
ee/spec/graphql/mutations/boards/update_spec.rb
0 → 100644
View file @
2e5179b0
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Mutations
::
Boards
::
Update
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:user
)
{
create
(
:user
)
}
let_it_be
(
:board
)
{
create
(
:board
,
project:
project
)
}
let_it_be
(
:milestone
)
{
create
(
:milestone
,
project:
project
)
}
let
(
:mutation
)
{
described_class
.
new
(
object:
nil
,
context:
{
current_user:
user
},
field:
nil
)
}
let
(
:mutated_board
)
{
subject
[
:board
]
}
specify
{
expect
(
described_class
).
to
require_graphql_authorizations
(
:admin_board
)
}
describe
'#resolve'
do
let
(
:mutation_params
)
do
{
id:
board
.
to_global_id
,
name:
'Test board 1'
,
hide_backlog_list:
true
,
hide_closed_list:
true
,
weight:
3
,
assignee_id:
user
.
to_global_id
,
milestone_id:
milestone
.
to_global_id
}
end
subject
{
mutation
.
resolve
(
mutation_params
)
}
context
'when the user cannot admin the board'
do
it
'raises an error'
do
expect
{
subject
}.
to
raise_error
(
Gitlab
::
Graphql
::
Errors
::
ResourceNotAvailable
)
end
end
context
'when user can update board'
do
before
do
board
.
resource_parent
.
add_reporter
(
user
)
end
it
'updates issue with correct values'
do
expected_attributes
=
{
name:
'Test board 1'
,
hide_backlog_list:
true
,
hide_closed_list:
true
,
weight:
3
,
assignee:
user
,
milestone:
milestone
}
subject
expect
(
board
.
reload
).
to
have_attributes
(
expected_attributes
)
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment