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
51b2591b
Commit
51b2591b
authored
Apr 28, 2021
by
Nathan Friend
Committed by
Jose Ivan Vargas
Apr 28, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Convert New and Edit Release pages to use GraphQL
parent
be8cc402
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
518 additions
and
385 deletions
+518
-385
app/assets/javascripts/releases/queries/create_release.mutation.graphql
...ascripts/releases/queries/create_release.mutation.graphql
+10
-0
app/assets/javascripts/releases/queries/create_release_link.mutation.graphql
...pts/releases/queries/create_release_link.mutation.graphql
+5
-0
app/assets/javascripts/releases/queries/delete_release_link.mutation.graphql
...pts/releases/queries/delete_release_link.mutation.graphql
+5
-0
app/assets/javascripts/releases/queries/update_release.mutation.graphql
...ascripts/releases/queries/update_release.mutation.graphql
+5
-0
app/assets/javascripts/releases/stores/modules/edit_new/actions.js
...s/javascripts/releases/stores/modules/edit_new/actions.js
+142
-110
app/assets/javascripts/releases/stores/modules/edit_new/getters.js
...s/javascripts/releases/stores/modules/edit_new/getters.js
+36
-0
app/assets/javascripts/releases/util.js
app/assets/javascripts/releases/util.js
+1
-45
changelogs/unreleased/nfriend-convert-release-new-edit-page-to-graphql.yml
...ased/nfriend-convert-release-new-edit-page-to-graphql.yml
+5
-0
locale/gitlab.pot
locale/gitlab.pot
+2
-2
spec/frontend/releases/stores/modules/detail/actions_spec.js
spec/frontend/releases/stores/modules/detail/actions_spec.js
+218
-126
spec/frontend/releases/stores/modules/detail/getters_spec.js
spec/frontend/releases/stores/modules/detail/getters_spec.js
+89
-0
spec/frontend/releases/util_spec.js
spec/frontend/releases/util_spec.js
+0
-102
No files found.
app/assets/javascripts/releases/queries/create_release.mutation.graphql
0 → 100644
View file @
51b2591b
mutation
createRelease
(
$input
:
ReleaseCreateInput
!)
{
releaseCreate
(
input
:
$input
)
{
release
{
links
{
selfUrl
}
}
errors
}
}
app/assets/javascripts/releases/queries/create_release_link.mutation.graphql
0 → 100644
View file @
51b2591b
mutation
createReleaseAssetLink
(
$input
:
ReleaseAssetLinkCreateInput
!)
{
releaseAssetLinkCreate
(
input
:
$input
)
{
errors
}
}
app/assets/javascripts/releases/queries/delete_release_link.mutation.graphql
0 → 100644
View file @
51b2591b
mutation
deleteReleaseAssetLink
(
$input
:
ReleaseAssetLinkDeleteInput
!)
{
releaseAssetLinkDelete
(
input
:
$input
)
{
errors
}
}
app/assets/javascripts/releases/queries/update_release.mutation.graphql
0 → 100644
View file @
51b2591b
mutation
updateRelease
(
$input
:
ReleaseUpdateInput
!)
{
releaseUpdate
(
input
:
$input
)
{
errors
}
}
app/assets/javascripts/releases/stores/modules/edit_new/actions.js
View file @
51b2591b
This diff is collapsed.
Click to expand it.
app/assets/javascripts/releases/stores/modules/edit_new/getters.js
View file @
51b2591b
...
...
@@ -103,3 +103,39 @@ export const isValid = (_state, getters) => {
const
errors
=
getters
.
validationErrors
;
return
Object
.
values
(
errors
.
assets
.
links
).
every
(
isEmpty
)
&&
!
errors
.
isTagNameEmpty
;
};
/** Returns all the variables for a `releaseUpdate` GraphQL mutation */
export
const
releaseUpdateMutatationVariables
=
(
state
)
=>
{
const
name
=
state
.
release
.
name
?.
trim
().
length
>
0
?
state
.
release
.
name
.
trim
()
:
null
;
// Milestones may be either a list of milestone objects OR just a list
// of milestone titles. The GraphQL mutation requires only the titles be sent.
const
milestones
=
(
state
.
release
.
milestones
||
[]).
map
((
m
)
=>
m
.
title
||
m
);
return
{
input
:
{
projectPath
:
state
.
projectPath
,
tagName
:
state
.
release
.
tagName
,
name
,
description
:
state
.
release
.
description
,
milestones
,
},
};
};
/** Returns all the variables for a `releaseCreate` GraphQL mutation */
export
const
releaseCreateMutatationVariables
=
(
state
,
getters
)
=>
{
return
{
input
:
{
...
getters
.
releaseUpdateMutatationVariables
.
input
,
ref
:
state
.
createFrom
,
assets
:
{
links
:
getters
.
releaseLinksToCreate
.
map
(({
name
,
url
,
linkType
})
=>
({
name
,
url
,
linkType
:
linkType
.
toUpperCase
(),
})),
},
},
};
};
app/assets/javascripts/releases/util.js
View file @
51b2591b
import
{
pick
}
from
'
lodash
'
;
import
createGqClient
,
{
fetchPolicies
}
from
'
~/lib/graphql
'
;
import
{
convertObjectPropsToCamelCase
,
convertObjectPropsToSnakeCase
,
}
from
'
~/lib/utils/common_utils
'
;
import
{
truncateSha
}
from
'
~/lib/utils/text_utility
'
;
/**
* Converts a release object into a JSON object that can sent to the public
* API to create or update a release.
* @param {Object} release The release object to convert
* @param {string} createFrom The ref to create a new tag from, if necessary
*/
export
const
releaseToApiJson
=
(
release
,
createFrom
=
null
)
=>
{
const
name
=
release
.
name
?.
trim
().
length
>
0
?
release
.
name
.
trim
()
:
null
;
// Milestones may be either a list of milestone objects OR just a list
// of milestone titles. The API requires only the titles be sent.
const
milestones
=
(
release
.
milestones
||
[]).
map
((
m
)
=>
m
.
title
||
m
);
return
convertObjectPropsToSnakeCase
(
{
name
,
tagName
:
release
.
tagName
,
ref
:
createFrom
,
description
:
release
.
description
,
milestones
,
assets
:
release
.
assets
,
},
{
deep
:
true
},
);
};
/**
* Converts a JSON release object returned by the Release API
* into the structure this Vue application can work with.
* @param {Object} json The JSON object received from the release API
*/
export
const
apiJsonToRelease
=
(
json
)
=>
{
const
release
=
convertObjectPropsToCamelCase
(
json
,
{
deep
:
true
});
release
.
milestones
=
release
.
milestones
||
[];
return
release
;
};
export
const
gqClient
=
createGqClient
({},
{
fetchPolicy
:
fetchPolicies
.
NO_CACHE
});
const
convertScalarProperties
=
(
graphQLRelease
)
=>
...
...
@@ -125,8 +82,7 @@ const convertMilestones = (graphQLRelease) => ({
/**
* Converts a single release object fetched from GraphQL
* into a release object that matches the shape of the REST API
* (the same shape that is returned by `apiJsonToRelease` above.)
* into a release object that matches the general structure of the REST API
*
* @param graphQLRelease The release object returned from a GraphQL query
*/
...
...
changelogs/unreleased/nfriend-convert-release-new-edit-page-to-graphql.yml
0 → 100644
View file @
51b2591b
---
title
:
Speed up save on New/Edit Release page
merge_request
:
57000
author
:
type
:
performance
locale/gitlab.pot
View file @
51b2591b
...
...
@@ -26663,13 +26663,13 @@ msgstr ""
msgid "Releases|New Release"
msgstr ""
msgid "Release|Something went wrong while creating a new release"
msgid "Release|Something went wrong while creating a new release
.
"
msgstr ""
msgid "Release|Something went wrong while getting the release details."
msgstr ""
msgid "Release|Something went wrong while saving the release details"
msgid "Release|Something went wrong while saving the release details
.
"
msgstr ""
msgid "Remediations"
...
...
spec/frontend/releases/stores/modules/detail/actions_spec.js
View file @
51b2591b
This diff is collapsed.
Click to expand it.
spec/frontend/releases/stores/modules/detail/getters_spec.js
View file @
51b2591b
...
...
@@ -257,4 +257,93 @@ describe('Release edit/new getters', () => {
});
});
});
describe
.
each
([
[
'
returns all the data needed for the releaseUpdate GraphQL query
'
,
{
projectPath
:
'
projectPath
'
,
release
:
{
tagName
:
'
release.tagName
'
,
name
:
'
release.name
'
,
description
:
'
release.description
'
,
milestones
:
[
'
release.milestone[0].title
'
],
},
},
{
projectPath
:
'
projectPath
'
,
tagName
:
'
release.tagName
'
,
name
:
'
release.name
'
,
description
:
'
release.description
'
,
milestones
:
[
'
release.milestone[0].title
'
],
},
],
[
'
trims whitespace from the release name
'
,
{
release
:
{
name
:
'
name
\t\n
'
}
},
{
name
:
'
name
'
},
],
[
'
returns the name as null if the name is nothing but whitespace
'
,
{
release
:
{
name
:
'
\t\n
'
}
},
{
name
:
null
},
],
[
'
returns the name as null if the name is undefined
'
,
{
release
:
{}
},
{
name
:
null
}],
[
'
returns just the milestone titles even if the release includes full milestone objects
'
,
{
release
:
{
milestones
:
[{
title
:
'
release.milestone[0].title
'
}]
}
},
{
milestones
:
[
'
release.milestone[0].title
'
]
},
],
])(
'
releaseUpdateMutatationVariables
'
,
(
description
,
state
,
expectedVariables
)
=>
{
it
(
description
,
()
=>
{
const
expectedVariablesObject
=
{
input
:
expect
.
objectContaining
(
expectedVariables
)
};
const
actualVariables
=
getters
.
releaseUpdateMutatationVariables
(
state
);
expect
(
actualVariables
).
toEqual
(
expectedVariablesObject
);
});
});
describe
(
'
releaseCreateMutatationVariables
'
,
()
=>
{
it
(
'
returns all the data needed for the releaseCreate GraphQL query
'
,
()
=>
{
const
state
=
{
createFrom
:
'
main
'
,
};
const
otherGetters
=
{
releaseUpdateMutatationVariables
:
{
input
:
{
name
:
'
release.name
'
,
},
},
releaseLinksToCreate
:
[
{
name
:
'
link.name
'
,
url
:
'
link.url
'
,
linkType
:
'
link.linkType
'
,
},
],
};
const
expectedVariables
=
{
input
:
{
name
:
'
release.name
'
,
ref
:
'
main
'
,
assets
:
{
links
:
[
{
name
:
'
link.name
'
,
url
:
'
link.url
'
,
linkType
:
'
LINK.LINKTYPE
'
,
},
],
},
},
};
const
actualVariables
=
getters
.
releaseCreateMutatationVariables
(
state
,
otherGetters
);
expect
(
actualVariables
).
toEqual
(
expectedVariables
);
});
});
});
spec/frontend/releases/util_spec.js
View file @
51b2591b
import
{
cloneDeep
}
from
'
lodash
'
;
import
{
getJSONFixture
}
from
'
helpers/fixtures
'
;
import
{
releaseToApiJson
,
apiJsonToRelease
,
convertGraphQLRelease
,
convertAllReleasesGraphQLResponse
,
convertOneReleaseGraphQLResponse
,
...
...
@@ -19,106 +17,6 @@ const originalOneReleaseForEditingQueryResponse = getJSONFixture(
);
describe
(
'
releases/util.js
'
,
()
=>
{
describe
(
'
releaseToApiJson
'
,
()
=>
{
it
(
'
converts a release JavaScript object into JSON that the Release API can accept
'
,
()
=>
{
const
release
=
{
tagName
:
'
tag-name
'
,
name
:
'
Release name
'
,
description
:
'
Release description
'
,
milestones
:
[
'
13.2
'
,
'
13.3
'
],
assets
:
{
links
:
[{
url
:
'
https://gitlab.example.com/link
'
,
linkType
:
'
other
'
}],
},
};
const
expectedJson
=
{
tag_name
:
'
tag-name
'
,
ref
:
null
,
name
:
'
Release name
'
,
description
:
'
Release description
'
,
milestones
:
[
'
13.2
'
,
'
13.3
'
],
assets
:
{
links
:
[{
url
:
'
https://gitlab.example.com/link
'
,
link_type
:
'
other
'
}],
},
};
expect
(
releaseToApiJson
(
release
)).
toEqual
(
expectedJson
);
});
describe
(
'
when createFrom is provided
'
,
()
=>
{
it
(
'
adds the provided createFrom ref to the JSON as a "ref" property
'
,
()
=>
{
const
createFrom
=
'
main
'
;
const
release
=
{};
const
expectedJson
=
{
ref
:
createFrom
,
};
expect
(
releaseToApiJson
(
release
,
createFrom
)).
toMatchObject
(
expectedJson
);
});
});
describe
(
'
release.name
'
,
()
=>
{
it
.
each
`
input | output
${
null
}
|
${
null
}
${
''
}
|
${
null
}
${
'
\t\n\r\n
'
}
|
${
null
}
${
'
Release name
'
}
|
${
'
Release name
'
}
`
(
'
converts a name like `$input` to `$output`
'
,
({
input
,
output
})
=>
{
const
release
=
{
name
:
input
};
const
expectedJson
=
{
name
:
output
,
};
expect
(
releaseToApiJson
(
release
)).
toMatchObject
(
expectedJson
);
});
});
describe
(
'
when milestones contains full milestone objects
'
,
()
=>
{
it
(
'
converts the milestone objects into titles
'
,
()
=>
{
const
release
=
{
milestones
:
[{
title
:
'
13.2
'
},
{
title
:
'
13.3
'
},
'
13.4
'
],
};
const
expectedJson
=
{
milestones
:
[
'
13.2
'
,
'
13.3
'
,
'
13.4
'
]
};
expect
(
releaseToApiJson
(
release
)).
toMatchObject
(
expectedJson
);
});
});
});
describe
(
'
apiJsonToRelease
'
,
()
=>
{
it
(
'
converts JSON received from the Release API into an object usable by the Vue application
'
,
()
=>
{
const
json
=
{
tag_name
:
'
tag-name
'
,
assets
:
{
links
:
[
{
link_type
:
'
other
'
,
},
],
},
};
const
expectedRelease
=
{
tagName
:
'
tag-name
'
,
assets
:
{
links
:
[
{
linkType
:
'
other
'
,
},
],
},
milestones
:
[],
};
expect
(
apiJsonToRelease
(
json
)).
toEqual
(
expectedRelease
);
});
});
describe
(
'
convertGraphQLRelease
'
,
()
=>
{
let
releaseFromResponse
;
let
convertedRelease
;
...
...
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