diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 15:40:28 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-07-20 15:40:28 +0000 |
commit | b595cb0c1dec83de5bdee18284abe86614bed33b (patch) | |
tree | 8c3d4540f193c5ff98019352f554e921b3a41a72 /app/assets/javascripts/releases | |
parent | 2f9104a328fc8a4bddeaa4627b595166d24671d0 (diff) | |
download | gitlab-ce-b595cb0c1dec83de5bdee18284abe86614bed33b.tar.gz |
Add latest changes from gitlab-org/gitlab@15-2-stable-eev15.2.0-rc42
Diffstat (limited to 'app/assets/javascripts/releases')
17 files changed, 248 insertions, 42 deletions
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue index 327da1fb2a1..022c3224bb4 100644 --- a/app/assets/javascripts/releases/components/app_edit_new.vue +++ b/app/assets/javascripts/releases/components/app_edit_new.vue @@ -1,5 +1,13 @@ <script> -import { GlButton, GlFormCheckbox, GlFormInput, GlFormGroup, GlLink, GlSprintf } from '@gitlab/ui'; +import { + GlButton, + GlDatepicker, + GlFormCheckbox, + GlFormInput, + GlFormGroup, + GlLink, + GlSprintf, +} from '@gitlab/ui'; import { mapState, mapActions, mapGetters } from 'vuex'; import { isSameOriginUrl, getParameterByName } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; @@ -7,6 +15,7 @@ import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue'; import { BACK_URL_PARAM } from '~/releases/constants'; import MarkdownField from '~/vue_shared/components/markdown/field.vue'; import AssetLinksForm from './asset_links_form.vue'; +import ConfirmDeleteModal from './confirm_delete_modal.vue'; import TagField from './tag_field.vue'; export default { @@ -16,8 +25,10 @@ export default { GlFormInput, GlFormGroup, GlButton, + GlDatepicker, GlLink, GlSprintf, + ConfirmDeleteModal, MarkdownField, AssetLinksForm, MilestoneCombobox, @@ -25,12 +36,14 @@ export default { }, computed: { ...mapState('editNew', [ + 'isExistingRelease', 'isFetchingRelease', 'isUpdatingRelease', 'fetchError', 'markdownDocsPath', 'markdownPreviewPath', 'editReleaseDocsPath', + 'upcomingReleaseDocsPath', 'releasesPagePath', 'release', 'newMilestonePath', @@ -40,7 +53,7 @@ export default { 'groupMilestonesAvailable', 'tagNotes', ]), - ...mapGetters('editNew', ['isValid', 'isExistingRelease', 'formattedReleaseNotes']), + ...mapGetters('editNew', ['isValid', 'formattedReleaseNotes']), showForm() { return Boolean(!this.isFetchingRelease && !this.fetchError && this.release); }, @@ -76,6 +89,14 @@ export default { this.updateIncludeTagNotes(includeTagNotes); }, }, + releasedAt: { + get() { + return this.release.releasedAt; + }, + set(date) { + this.updateReleasedAt(date); + }, + }, cancelPath() { const backUrl = getParameterByName(BACK_URL_PARAM); @@ -114,10 +135,12 @@ export default { ...mapActions('editNew', [ 'initializeRelease', 'saveRelease', + 'deleteRelease', 'updateReleaseTitle', 'updateReleaseNotes', 'updateReleaseMilestones', 'updateIncludeTagNotes', + 'updateReleasedAt', ]), submitForm() { if (!this.isFormSubmissionDisabled) { @@ -166,6 +189,22 @@ export default { /> </div> </gl-form-group> + <gl-form-group :label="__('Release date')" label-for="release-released-at"> + <template #label-description> + <gl-sprintf + :message=" + __( + 'The date when the release is ready. A release with a date in the future is labeled as an %{linkStart}Upcoming Release%{linkEnd}.', + ) + " + > + <template #link="{ content }"> + <gl-link :href="upcomingReleaseDocsPath">{{ content }}</gl-link> + </template> + </gl-sprintf> + </template> + <gl-datepicker id="release-released-at" v-model="releasedAt" :default-date="releasedAt" /> + </gl-form-group> <gl-form-group data-testid="release-notes"> <label for="release-notes">{{ __('Release notes') }}</label> <div class="bordered-box pr-3 pl-3"> @@ -224,6 +263,7 @@ export default { > {{ saveButtonLabel }} </gl-button> + <confirm-delete-modal v-if="isExistingRelease" @delete="deleteRelease" /> <gl-button :href="cancelPath" class="js-cancel-button">{{ __('Cancel') }}</gl-button> </div> </form> diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue index a949a9d1318..d63a83d1a08 100644 --- a/app/assets/javascripts/releases/components/app_index.vue +++ b/app/assets/javascripts/releases/components/app_index.vue @@ -4,9 +4,9 @@ import createFlash from '~/flash'; import { historyPushState } from '~/lib/utils/common_utils'; import { scrollUp } from '~/lib/utils/scroll_utils'; import { setUrlParams, getParameterByName } from '~/lib/utils/url_utility'; -import { __ } from '~/locale'; +import { __, sprintf } from '~/locale'; import { PAGE_SIZE, DEFAULT_SORT } from '~/releases/constants'; -import { convertAllReleasesGraphQLResponse } from '~/releases/util'; +import { convertAllReleasesGraphQLResponse, deleteReleaseSessionKey } from '~/releases/util'; import allReleasesQuery from '../graphql/queries/all_releases.query.graphql'; import ReleaseBlock from './release_block.vue'; import ReleaseSkeletonLoader from './release_skeleton_loader.vue'; @@ -172,6 +172,20 @@ export default { return this.isFullRequestLoaded && !this.shouldRenderEmptyState; }, }, + mounted() { + const key = deleteReleaseSessionKey(this.projectPath); + const deletedRelease = window.sessionStorage.getItem(key); + + if (deletedRelease) { + this.$toast.show( + sprintf(__('Release %{deletedRelease} has been successfully deleted.'), { + deletedRelease, + }), + ); + } + + window.sessionStorage.removeItem(key); + }, created() { this.updateQueryParamsFromUrl(); diff --git a/app/assets/javascripts/releases/components/confirm_delete_modal.vue b/app/assets/javascripts/releases/components/confirm_delete_modal.vue new file mode 100644 index 00000000000..aa948fbbaf6 --- /dev/null +++ b/app/assets/javascripts/releases/components/confirm_delete_modal.vue @@ -0,0 +1,77 @@ +<script> +import { GlModal, GlSprintf, GlLink, GlButton } from '@gitlab/ui'; +import { mapState } from 'vuex'; +import { __, s__, sprintf } from '~/locale'; + +export default { + components: { + GlModal, + GlSprintf, + GlLink, + GlButton, + }, + data() { + return { + visible: false, + }; + }, + computed: { + ...mapState('editNew', ['release', 'deleteReleaseDocsPath']), + title() { + return sprintf(__('Delete release %{release}?'), { release: this.release.name }); + }, + }, + modalOptions: { + modalId: 'confirm-delete-release', + static: true, + actionPrimary: { + attributes: { variant: 'danger' }, + text: __('Delete release'), + }, + actionSecondary: { + text: __('Cancel'), + attributes: { variant: 'default' }, + }, + }, + i18n: { + buttonLabel: __('Delete'), + line1: s__( + 'DeleteRelease|You are about to delete release %{release} and its assets. The Git tag %{tag} will not be deleted.', + ), + line2: s__( + 'DeleteRelease|For more details, see %{docsPathStart}Deleting a release%{docsPathEnd}.', + ), + line3: s__('DeleteRelease|Are you sure you want to delete this release?'), + }, +}; +</script> +<template> + <div> + <gl-button class="gl-mr-3" variant="danger" @click="visible = true"> + {{ $options.i18n.buttonLabel }} + </gl-button> + <gl-modal + v-bind="$options.modalOptions" + v-model="visible" + :title="title" + @primary="$emit('delete')" + > + <p> + <gl-sprintf :message="$options.i18n.line1"> + <template #release>{{ release.name }}</template> + <template #tag> + <gl-link :href="release.tagPath">{{ release.tagName }}</gl-link> + </template> + </gl-sprintf> + </p> + <p> + <gl-sprintf :message="$options.i18n.line2"> + <template #docsPath="{ content }"> + <gl-link :href="deleteReleaseDocsPath" target="_blank">{{ content }}</gl-link> + </template> + </gl-sprintf> + </p> + <p>{{ $options.i18n.line3 }}</p> + </gl-modal> + </div> +</template> diff --git a/app/assets/javascripts/releases/components/release_block_footer.vue b/app/assets/javascripts/releases/components/release_block_footer.vue index 91d6d0911a4..3881c83b5c2 100644 --- a/app/assets/javascripts/releases/components/release_block_footer.vue +++ b/app/assets/javascripts/releases/components/release_block_footer.vue @@ -42,9 +42,9 @@ export default { default: null, }, releasedAt: { - type: String, + type: Date, required: false, - default: '', + default: null, }, }, computed: { @@ -66,8 +66,11 @@ export default { </script> <template> <div> - <div v-if="commit" class="float-left mr-3 d-flex align-items-center js-commit-info"> - <gl-icon ref="commitIcon" name="commit" class="mr-1" /> + <div + v-if="commit" + class="gl-float-left gl-mr-5 gl-display-flex gl-align-items-center js-commit-info" + > + <gl-icon ref="commitIcon" name="commit" class="gl-mr-2" /> <div v-gl-tooltip.bottom :title="commit.title"> <gl-link v-if="commitPath" :href="commitPath"> {{ commit.shortId }} @@ -76,8 +79,11 @@ export default { </div> </div> - <div v-if="tagName" class="float-left mr-3 d-flex align-items-center js-tag-info"> - <gl-icon name="tag" class="mr-1" /> + <div + v-if="tagName" + class="gl-float-left gl-mr-5 gl-display-flex gl-align-items-center js-tag-info" + > + <gl-icon name="tag" class="gl-mr-2" /> <div v-gl-tooltip.bottom :title="__('Tag')"> <gl-link v-if="tagPath" :href="tagPath"> {{ tagName }} @@ -88,23 +94,23 @@ export default { <div v-if="releasedAt || author" - class="float-left d-flex align-items-center js-author-date-info" + class="gl-float-left gl-display-flex gl-align-items-center js-author-date-info" > - <span class="text-secondary">{{ createdTime }} </span> + <span class="gl-text-secondary">{{ createdTime }} </span> <template v-if="releasedAt"> <span v-gl-tooltip.bottom :title="tooltipTitle(releasedAt)" - class="text-secondary flex-shrink-0" + class="gl-text-secondary gl-flex-shrink-0" > {{ releasedAtTimeAgo }} </span> </template> - <div v-if="author" class="d-flex"> - <span class="text-secondary">{{ __('by') }} </span> + <div v-if="author" class="gl-display-flex"> + <span class="gl-text-secondary">{{ __('by') }} </span> <user-avatar-link - class="gl-my-n1" + class="gl-my-n1 gl-display-flex" :link-href="author.webUrl" :img-src="author.avatarUrl" :img-alt="userImageAltDescription" diff --git a/app/assets/javascripts/releases/components/tag_field.vue b/app/assets/javascripts/releases/components/tag_field.vue index f4c0fd5e9ce..b4fea9bee35 100644 --- a/app/assets/javascripts/releases/components/tag_field.vue +++ b/app/assets/javascripts/releases/components/tag_field.vue @@ -1,5 +1,5 @@ <script> -import { mapGetters } from 'vuex'; +import { mapState } from 'vuex'; import TagFieldExisting from './tag_field_existing.vue'; import TagFieldNew from './tag_field_new.vue'; @@ -9,7 +9,7 @@ export default { TagFieldNew, }, computed: { - ...mapGetters('editNew', ['isExistingRelease']), + ...mapState('editNew', ['isExistingRelease']), }, }; </script> diff --git a/app/assets/javascripts/releases/components/tag_field_new.vue b/app/assets/javascripts/releases/components/tag_field_new.vue index d3b6d07590f..08b727dcca0 100644 --- a/app/assets/javascripts/releases/components/tag_field_new.vue +++ b/app/assets/javascripts/releases/components/tag_field_new.vue @@ -22,12 +22,10 @@ export default { // the input field. This is used to avoid showing validation // errors immediately when the page loads. isInputDirty: false, - - showCreateFrom: true, }; }, computed: { - ...mapState('editNew', ['projectId', 'release', 'createFrom']), + ...mapState('editNew', ['projectId', 'release', 'createFrom', 'showCreateFrom']), ...mapGetters('editNew', ['validationErrors']), tagName: { get() { @@ -40,7 +38,7 @@ export default { // When this is called, the selection originated from the // dropdown list of existing tag names, so we know the tag // already exists and don't need to show the "create from" input - this.showCreateFrom = false; + this.updateShowCreateFrom(false); }, }, createFromModel: { @@ -70,7 +68,12 @@ export default { }, }, methods: { - ...mapActions('editNew', ['updateReleaseTagName', 'updateCreateFrom', 'fetchTagNotes']), + ...mapActions('editNew', [ + 'updateReleaseTagName', + 'updateCreateFrom', + 'fetchTagNotes', + 'updateShowCreateFrom', + ]), markInputAsDirty() { this.isInputDirty = true; }, @@ -80,7 +83,7 @@ export default { // This method is called when the user selects the "create tag" // option, so the tag does not already exist. Because of this, // we need to show the "create from" input. - this.showCreateFrom = true; + this.updateShowCreateFrom(true); }, shouldShowCreateTagOption(isLoading, matches, query) { // Show the "create tag" option if: diff --git a/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql b/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql index 236d266a40a..3ad66afa259 100644 --- a/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql +++ b/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql @@ -3,6 +3,8 @@ fragment ReleaseForEditing on Release { name tagName description + releasedAt + tagPath assets { links { nodes { diff --git a/app/assets/javascripts/releases/graphql/mutations/delete_release.mutation.graphql b/app/assets/javascripts/releases/graphql/mutations/delete_release.mutation.graphql new file mode 100644 index 00000000000..7a8bf9944a3 --- /dev/null +++ b/app/assets/javascripts/releases/graphql/mutations/delete_release.mutation.graphql @@ -0,0 +1,5 @@ +mutation deleteRelease($input: ReleaseDeleteInput!) { + releaseDelete(input: $input) { + errors + } +} diff --git a/app/assets/javascripts/releases/mount_edit.js b/app/assets/javascripts/releases/mount_edit.js index fad0451ceef..c3130a0b778 100644 --- a/app/assets/javascripts/releases/mount_edit.js +++ b/app/assets/javascripts/releases/mount_edit.js @@ -11,7 +11,7 @@ export default () => { const store = createStore({ modules: { - editNew: createEditNewModule(el.dataset), + editNew: createEditNewModule({ ...el.dataset, isExistingRelease: true }), }, }); diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js index afb8ab461cd..8e806f0e8d7 100644 --- a/app/assets/javascripts/releases/mount_index.js +++ b/app/assets/javascripts/releases/mount_index.js @@ -1,5 +1,6 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; +import { GlToast } from '@gitlab/ui'; import createDefaultClient from '~/lib/graphql'; import ReleaseIndexApp from './components/app_index.vue'; @@ -7,6 +8,7 @@ export default () => { const el = document.getElementById('js-releases-page'); Vue.use(VueApollo); + Vue.use(GlToast); const apolloProvider = new VueApollo({ defaultClient: createDefaultClient( diff --git a/app/assets/javascripts/releases/mount_new.js b/app/assets/javascripts/releases/mount_new.js index b358a27f06d..0a3f8b5e63b 100644 --- a/app/assets/javascripts/releases/mount_new.js +++ b/app/assets/javascripts/releases/mount_new.js @@ -11,7 +11,7 @@ export default () => { const store = createStore({ modules: { - editNew: createEditNewModule(el.dataset), + editNew: createEditNewModule({ ...el.dataset, isExistingRelease: false }), }, }); diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js index 08197377f61..a71a8125d65 100644 --- a/app/assets/javascripts/releases/stores/modules/edit_new/actions.js +++ b/app/assets/javascripts/releases/stores/modules/edit_new/actions.js @@ -3,16 +3,21 @@ import createFlash from '~/flash'; import { redirectTo } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import createReleaseMutation from '~/releases/graphql/mutations/create_release.mutation.graphql'; +import deleteReleaseMutation from '~/releases/graphql/mutations/delete_release.mutation.graphql'; import createReleaseAssetLinkMutation from '~/releases/graphql/mutations/create_release_link.mutation.graphql'; import deleteReleaseAssetLinkMutation from '~/releases/graphql/mutations/delete_release_link.mutation.graphql'; import updateReleaseMutation from '~/releases/graphql/mutations/update_release.mutation.graphql'; import oneReleaseForEditingQuery from '~/releases/graphql/queries/one_release_for_editing.query.graphql'; -import { gqClient, convertOneReleaseGraphQLResponse } from '~/releases/util'; +import { + gqClient, + convertOneReleaseGraphQLResponse, + deleteReleaseSessionKey, +} from '~/releases/util'; import * as types from './mutation_types'; -export const initializeRelease = ({ commit, dispatch, getters }) => { - if (getters.isExistingRelease) { +export const initializeRelease = ({ commit, dispatch, state }) => { + if (state.isExistingRelease) { // When editing an existing release, // fetch the release object from the API return dispatch('fetchRelease'); @@ -53,6 +58,9 @@ export const updateReleaseTagName = ({ commit }, tagName) => export const updateCreateFrom = ({ commit }, createFrom) => commit(types.UPDATE_CREATE_FROM, createFrom); +export const updateShowCreateFrom = ({ commit }, showCreateFrom) => + commit(types.UPDATE_SHOW_CREATE_FROM, showCreateFrom); + export const updateReleaseTitle = ({ commit }, title) => commit(types.UPDATE_RELEASE_TITLE, title); export const updateReleaseNotes = ({ commit }, notes) => commit(types.UPDATE_RELEASE_NOTES, notes); @@ -88,10 +96,10 @@ export const receiveSaveReleaseSuccess = ({ commit }, urlToRedirectTo) => { redirectTo(urlToRedirectTo); }; -export const saveRelease = ({ commit, dispatch, getters }) => { +export const saveRelease = ({ commit, dispatch, state }) => { commit(types.REQUEST_SAVE_RELEASE); - dispatch(getters.isExistingRelease ? 'updateRelease' : 'createRelease'); + dispatch(state.isExistingRelease ? 'updateRelease' : 'createRelease'); }; /** @@ -246,3 +254,30 @@ export const fetchTagNotes = ({ commit, state }, tagName) => { export const updateIncludeTagNotes = ({ commit }, includeTagNotes) => { commit(types.UPDATE_INCLUDE_TAG_NOTES, includeTagNotes); }; + +export const updateReleasedAt = ({ commit }, releasedAt) => { + commit(types.UPDATE_RELEASED_AT, releasedAt); +}; + +export const deleteRelease = ({ commit, getters, dispatch, state }) => { + commit(types.REQUEST_SAVE_RELEASE); + return gqClient + .mutate({ + mutation: deleteReleaseMutation, + variables: getters.releaseDeleteMutationVariables, + }) + .then((response) => checkForErrorsAsData(response, 'releaseDelete', '')) + .then(() => { + window.sessionStorage.setItem( + deleteReleaseSessionKey(state.projectPath), + state.originalRelease.name, + ); + return dispatch('receiveSaveReleaseSuccess', state.releasesPagePath); + }) + .catch((error) => { + commit(types.RECEIVE_SAVE_RELEASE_ERROR, error); + createFlash({ + message: s__('Release|Something went wrong while deleting the release.'), + }); + }); +}; diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/getters.js b/app/assets/javascripts/releases/stores/modules/edit_new/getters.js index 0ca5eb9931a..62d6bd42d51 100644 --- a/app/assets/javascripts/releases/stores/modules/edit_new/getters.js +++ b/app/assets/javascripts/releases/stores/modules/edit_new/getters.js @@ -4,14 +4,6 @@ import { hasContent } from '~/lib/utils/text_utility'; import { getDuplicateItemsFromArray } from '~/lib/utils/array_utility'; /** - * @returns {Boolean} `true` if the app is editing an existing release. - * `false` if the app is creating a new release. - */ -export const isExistingRelease = (state) => { - return Boolean(state.tagName); -}; - -/** * @param {Object} link The link to test * @returns {Boolean} `true` if the release link is empty, i.e. it has * empty (or whitespace-only) values for both `url` and `name`. @@ -138,6 +130,7 @@ export const releaseUpdateMutatationVariables = (state, getters) => { projectPath: state.projectPath, tagName: state.release.tagName, name, + releasedAt: state.release.releasedAt, description: state.includeTagNotes ? getters.formattedReleaseNotes : state.release.description, @@ -163,6 +156,13 @@ export const releaseCreateMutatationVariables = (state, getters) => { }; }; +export const releaseDeleteMutationVariables = (state) => ({ + input: { + projectPath: state.projectPath, + tagName: state.release.tagName, + }, +}); + export const formattedReleaseNotes = ({ includeTagNotes, release: { description }, tagNotes }) => includeTagNotes && tagNotes ? `${description}\n\n### ${s__('Releases|Tag message')}\n\n${tagNotes}\n` diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js b/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js index daa077309a1..0ef017f4eb4 100644 --- a/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js +++ b/app/assets/javascripts/releases/stores/modules/edit_new/mutation_types.js @@ -6,6 +6,7 @@ export const RECEIVE_RELEASE_ERROR = 'RECEIVE_RELEASE_ERROR'; export const UPDATE_RELEASE_TAG_NAME = 'UPDATE_RELEASE_TAG_NAME'; export const UPDATE_CREATE_FROM = 'UPDATE_CREATE_FROM'; +export const UPDATE_SHOW_CREATE_FROM = 'UPDATE_SHOW_CREATE_FROM'; export const UPDATE_RELEASE_TITLE = 'UPDATE_RELEASE_TITLE'; export const UPDATE_RELEASE_NOTES = 'UPDATE_RELEASE_NOTES'; export const UPDATE_RELEASE_MILESTONES = 'UPDATE_RELEASE_MILESTONES'; @@ -26,3 +27,4 @@ export const RECEIVE_TAG_NOTES_SUCCESS = 'RECEIVE_TAG_NOTES_SUCCESS'; export const RECEIVE_TAG_NOTES_ERROR = 'RECEIVE_TAG_NOTES_ERROR'; export const UPDATE_INCLUDE_TAG_NOTES = 'UPDATE_INCLUDE_TAG_NOTES'; +export const UPDATE_RELEASED_AT = 'UPDATE_RELEASED_AT'; diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js b/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js index 6b22468bbfe..ea794f91f66 100644 --- a/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js +++ b/app/assets/javascripts/releases/stores/modules/edit_new/mutations.js @@ -9,11 +9,12 @@ const findReleaseLink = (release, id) => { export default { [types.INITIALIZE_EMPTY_RELEASE](state) { state.release = { - tagName: null, + tagName: state.tagName, name: '', description: '', milestones: [], groupMilestones: [], + releasedAt: new Date(), assets: { links: [], }, @@ -41,6 +42,9 @@ export default { [types.UPDATE_CREATE_FROM](state, createFrom) { state.createFrom = createFrom; }, + [types.UPDATE_SHOW_CREATE_FROM](state, showCreateFrom) { + state.showCreateFrom = showCreateFrom; + }, [types.UPDATE_RELEASE_TITLE](state, title) { state.release.name = title; }, @@ -113,4 +117,7 @@ export default { [types.UPDATE_INCLUDE_TAG_NOTES](state, includeTagNotes) { state.includeTagNotes = includeTagNotes; }, + [types.UPDATE_RELEASED_AT](state, releasedAt) { + state.release.releasedAt = releasedAt; + }, }; diff --git a/app/assets/javascripts/releases/stores/modules/edit_new/state.js b/app/assets/javascripts/releases/stores/modules/edit_new/state.js index 33cb3ee06d0..cb447cf9aaf 100644 --- a/app/assets/javascripts/releases/stores/modules/edit_new/state.js +++ b/app/assets/javascripts/releases/stores/modules/edit_new/state.js @@ -1,4 +1,5 @@ export default ({ + isExistingRelease, projectId, groupId, groupMilestonesAvailable = false, @@ -10,10 +11,13 @@ export default ({ newMilestonePath, releasesPagePath, editReleaseDocsPath, + upcomingReleaseDocsPath, + deleteReleaseDocsPath = '', tagName = null, defaultBranch = null, }) => ({ + isExistingRelease, projectId, groupId, groupMilestonesAvailable: Boolean(groupMilestonesAvailable), @@ -25,12 +29,15 @@ export default ({ newMilestonePath, releasesPagePath, editReleaseDocsPath, + upcomingReleaseDocsPath, + deleteReleaseDocsPath, /** * The name of the tag associated with the release, provided by the backend. - * When creating a new release, this value is null. + * When creating a new release, this is the default from the URL */ tagName, + showCreateFrom: !tagName, defaultBranch, createFrom: defaultBranch, diff --git a/app/assets/javascripts/releases/util.js b/app/assets/javascripts/releases/util.js index 22d5fb4f620..f1f5f4bca4c 100644 --- a/app/assets/javascripts/releases/util.js +++ b/app/assets/javascripts/releases/util.js @@ -11,10 +11,13 @@ const convertScalarProperties = (graphQLRelease) => 'tagPath', 'description', 'descriptionHtml', - 'releasedAt', 'upcomingRelease', ]); +const convertDateProperties = ({ releasedAt }) => ({ + releasedAt: new Date(releasedAt), +}); + const convertAssets = (graphQLRelease) => { let sources = []; if (graphQLRelease.assets.sources?.nodes) { @@ -88,6 +91,7 @@ const convertMilestones = (graphQLRelease) => ({ */ export const convertGraphQLRelease = (graphQLRelease) => ({ ...convertScalarProperties(graphQLRelease), + ...convertDateProperties(graphQLRelease), ...convertAssets(graphQLRelease), ...convertEvidences(graphQLRelease), ...convertLinks(graphQLRelease), @@ -129,3 +133,5 @@ export const convertOneReleaseGraphQLResponse = (response) => { return { data: release }; }; + +export const deleteReleaseSessionKey = (projectPath) => `deleteRelease:${projectPath}`; |