Commit 7f9af793 authored by Miguel Rincon's avatar Miguel Rincon

Merge branch 'nfriend-implement-new-tag-field' into 'master'

Replace `new_tag_field.vue` placeholder with real implementation

See merge request gitlab-org/gitlab!37730
parents 098ef5a0 75bf3251
<script>
export default {
name: 'FormFieldContainer',
};
</script>
<template>
<div class="row">
<div class="col-md-6 col-lg-5 col-xl-4 gl-display-flex gl-flex-direction-column">
<slot></slot>
</div>
</div>
</template>
......@@ -2,10 +2,11 @@
import { mapState } from 'vuex';
import { uniqueId } from 'lodash';
import { GlFormGroup, GlFormInput, GlLink, GlSprintf } from '@gitlab/ui';
import FormFieldContainer from './form_field_container.vue';
export default {
name: 'TagFieldExisting',
components: { GlFormGroup, GlFormInput, GlSprintf, GlLink },
components: { GlFormGroup, GlFormInput, GlSprintf, GlLink, FormFieldContainer },
computed: {
...mapState('detail', ['release', 'updateReleaseApiDocsPath']),
inputId() {
......@@ -19,18 +20,16 @@ export default {
</script>
<template>
<gl-form-group :label="__('Tag name')" :label-for="inputId">
<div class="row">
<div class="col-md-6 col-lg-5 col-xl-4">
<gl-form-input
:id="inputId"
:value="release.tagName"
type="text"
class="form-control"
:aria-describedby="helpId"
disabled
/>
</div>
</div>
<form-field-container>
<gl-form-input
:id="inputId"
:value="release.tagName"
type="text"
class="form-control"
:aria-describedby="helpId"
disabled
/>
</form-field-container>
<template #description>
<div :id="helpId" data-testid="tag-name-help">
<gl-sprintf
......
<script>
import { mapState, mapActions } from 'vuex';
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { __ } from '~/locale';
import RefSelector from '~/ref/components/ref_selector.vue';
import FormFieldContainer from './form_field_container.vue';
export default {
name: 'TagFieldNew',
components: { GlFormGroup, GlFormInput, RefSelector, FormFieldContainer },
computed: {
...mapState('detail', ['projectId', 'release', 'createFrom']),
tagName: {
get() {
return this.release.tagName;
},
set(tagName) {
this.updateReleaseTagName(tagName);
},
},
createFromModel: {
get() {
return this.createFrom;
},
set(createFrom) {
this.updateCreateFrom(createFrom);
},
},
tagNameInputId() {
return uniqueId('tag-name-input-');
},
createFromSelectorId() {
return uniqueId('create-from-selector-');
},
},
methods: {
...mapActions('detail', ['updateReleaseTagName', 'updateCreateFrom']),
},
translations: {
noRefSelected: __('No source selected'),
searchPlaceholder: __('Search branches, tags, and commits'),
dropdownHeader: __('Select source'),
},
};
</script>
<template>
<div></div>
<div>
<gl-form-group :label="__('Tag name')" :label-for="tagNameInputId" data-testid="tag-name-field">
<form-field-container>
<gl-form-input :id="tagNameInputId" v-model="tagName" type="text" class="form-control" />
</form-field-container>
</gl-form-group>
<gl-form-group
:label="__('Create from')"
:label-for="createFromSelectorId"
data-testid="create-from-field"
>
<form-field-container>
<ref-selector
:id="createFromSelectorId"
v-model="createFromModel"
:project-id="projectId"
:translations="$options.translations"
/>
</form-field-container>
<template #description>
{{ __('Existing branch name, tag, or commit SHA') }}
</template>
</gl-form-group>
</div>
</template>
......@@ -34,6 +34,10 @@ export const fetchRelease = ({ dispatch, state }) => {
});
};
export const updateReleaseTagName = ({ commit }, tagName) =>
commit(types.UPDATE_RELEASE_TAG_NAME, tagName);
export const updateCreateFrom = ({ commit }, createFrom) =>
commit(types.UPDATE_CREATE_FROM, createFrom);
export const updateReleaseTitle = ({ commit }, title) => commit(types.UPDATE_RELEASE_TITLE, title);
export const updateReleaseNotes = ({ commit }, notes) => commit(types.UPDATE_RELEASE_NOTES, notes);
export const updateReleaseMilestones = ({ commit }, milestones) =>
......
......@@ -2,6 +2,8 @@ export const REQUEST_RELEASE = 'REQUEST_RELEASE';
export const RECEIVE_RELEASE_SUCCESS = 'RECEIVE_RELEASE_SUCCESS';
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_RELEASE_TITLE = 'UPDATE_RELEASE_TITLE';
export const UPDATE_RELEASE_NOTES = 'UPDATE_RELEASE_NOTES';
export const UPDATE_RELEASE_MILESTONES = 'UPDATE_RELEASE_MILESTONES';
......
......@@ -22,6 +22,12 @@ export default {
state.release = undefined;
},
[types.UPDATE_RELEASE_TAG_NAME](state, tagName) {
state.release.tagName = tagName;
},
[types.UPDATE_CREATE_FROM](state, createFrom) {
state.createFrom = createFrom;
},
[types.UPDATE_RELEASE_TITLE](state, title) {
state.release.name = title;
},
......
......@@ -27,6 +27,7 @@ export default ({
releasesPagePath,
defaultBranch,
createFrom: defaultBranch,
/** The Release object */
release: null,
......
......@@ -7024,6 +7024,9 @@ msgstr ""
msgid "Create file"
msgstr ""
msgid "Create from"
msgstr ""
msgid "Create group"
msgstr ""
......@@ -9884,6 +9887,9 @@ msgstr ""
msgid "Excluding merge commits. Limited to 6,000 commits."
msgstr ""
msgid "Existing branch name, tag, or commit SHA"
msgstr ""
msgid "Existing members and groups"
msgstr ""
......@@ -16325,6 +16331,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
msgid "No source selected"
msgstr ""
msgid "No stack trace for this error"
msgstr ""
......@@ -21100,6 +21109,9 @@ msgstr ""
msgid "Search branches and tags"
msgstr ""
msgid "Search branches, tags, and commits"
msgstr ""
msgid "Search by Git revision"
msgstr ""
......@@ -21729,6 +21741,9 @@ msgstr ""
msgid "Select shards to replicate"
msgstr ""
msgid "Select source"
msgstr ""
msgid "Select source branch"
msgstr ""
......
import { shallowMount } from '@vue/test-utils';
import { GlFormInput } from '@gitlab/ui';
import TagFieldNew from '~/releases/components/tag_field_new.vue';
import createStore from '~/releases/stores';
import createDetailModule from '~/releases/stores/modules/detail';
import RefSelector from '~/ref/components/ref_selector.vue';
const TEST_TAG_NAME = 'test-tag-name';
const TEST_PROJECT_ID = '1234';
const TEST_CREATE_FROM = 'test-create-from';
describe('releases/components/tag_field_new', () => {
let store;
......@@ -16,9 +22,17 @@ describe('releases/components/tag_field_new', () => {
beforeEach(() => {
store = createStore({
modules: {
detail: createDetailModule({}),
detail: createDetailModule({
projectId: TEST_PROJECT_ID,
}),
},
});
store.state.detail.createFrom = TEST_CREATE_FROM;
store.state.detail.release = {
tagName: TEST_TAG_NAME,
};
});
afterEach(() => {
......@@ -26,9 +40,47 @@ describe('releases/components/tag_field_new', () => {
wrapper = null;
});
it('renders a placeholder component', () => {
createComponent();
const findTagNameFormGroup = () => wrapper.find('[data-testid="tag-name-field"]');
const findTagNameGlInput = () => findTagNameFormGroup().find(GlFormInput);
const findCreateFromFormGroup = () => wrapper.find('[data-testid="create-from-field"]');
const findCreateFromDropdown = () => findCreateFromFormGroup().find(RefSelector);
describe('"Tag name" field', () => {
beforeEach(createComponent);
it('renders a label', () => {
expect(findTagNameFormGroup().attributes().label).toBe('Tag name');
});
describe('when the user updates the field', () => {
it("updates the store's release.tagName property", () => {
const updatedTagName = 'updated-tag-name';
findTagNameGlInput().vm.$emit('input', updatedTagName);
return wrapper.vm.$nextTick().then(() => {
expect(store.state.detail.release.tagName).toBe(updatedTagName);
});
});
});
});
describe('"Create from" field', () => {
beforeEach(createComponent);
expect(wrapper.exists()).toBe(true);
it('renders a label', () => {
expect(findCreateFromFormGroup().attributes().label).toBe('Create from');
});
describe('when the user selects a git ref', () => {
it("updates the store's createFrom property", () => {
const updatedCreateFrom = 'update-create-from';
findCreateFromDropdown().vm.$emit('input', updatedCreateFrom);
return wrapper.vm.$nextTick().then(() => {
expect(store.state.detail.createFrom).toBe(updatedCreateFrom);
});
});
});
});
});
......@@ -113,6 +113,24 @@ describe('Release detail actions', () => {
});
});
describe('updateReleaseTagName', () => {
it(`commits ${types.UPDATE_RELEASE_TAG_NAME} with the updated tag name`, () => {
const newTag = 'updated-tag-name';
return testAction(actions.updateReleaseTagName, newTag, state, [
{ type: types.UPDATE_RELEASE_TAG_NAME, payload: newTag },
]);
});
});
describe('updateCreateFrom', () => {
it(`commits ${types.UPDATE_CREATE_FROM} with the updated ref`, () => {
const newRef = 'my-feature-branch';
return testAction(actions.updateCreateFrom, newRef, state, [
{ type: types.UPDATE_CREATE_FROM, payload: newRef },
]);
});
});
describe('updateReleaseTitle', () => {
it(`commits ${types.UPDATE_RELEASE_TITLE} with the updated release title`, () => {
const newTitle = 'The new release title';
......
......@@ -56,6 +56,26 @@ describe('Release detail mutations', () => {
});
});
describe(`${types.UPDATE_RELEASE_TAG_NAME}`, () => {
it("updates the release's tag name", () => {
state.release = release;
const newTag = 'updated-tag-name';
mutations[types.UPDATE_RELEASE_TAG_NAME](state, newTag);
expect(state.release.tagName).toBe(newTag);
});
});
describe(`${types.UPDATE_CREATE_FROM}`, () => {
it('updates the ref that the ref will be created from', () => {
state.createFrom = 'main';
const newRef = 'my-feature-branch';
mutations[types.UPDATE_CREATE_FROM](state, newRef);
expect(state.createFrom).toBe(newRef);
});
});
describe(`${types.UPDATE_RELEASE_TITLE}`, () => {
it("updates the release's title", () => {
state.release = release;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment