Commit 2b98addb authored by Axel García's avatar Axel García

Update epic form to use stacked form groups

This also updates tests and strings accordingly
parent ec86096e
<script>
import { GlButton, GlDatepicker, GlForm, GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import {
GlButton,
GlDatepicker,
GlForm,
GlFormCheckbox,
GlFormGroup,
GlFormInput,
} from '@gitlab/ui';
import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
import createFlash from '~/flash';
import { __ } from '~/locale';
......@@ -14,6 +21,7 @@ export default {
GlForm,
GlFormCheckbox,
GlFormInput,
GlFormGroup,
MarkdownField,
LabelsSelectVue,
},
......@@ -81,16 +89,15 @@ export default {
const { errors, epic } = data.createEpic;
if (errors?.length > 0) {
createFlash(errors[0]);
this.loading = false;
return;
}
visitUrl(epic.webUrl);
})
.catch(() => {
createFlash(__('Unable to save epic. Please try again'));
})
.finally(() => {
this.loading = false;
createFlash(__('Unable to save epic. Please try again'));
});
},
updateDueDate(val) {
......@@ -118,26 +125,18 @@ export default {
<div>
<h3 class="page-title">{{ __('New Epic') }}</h3>
<hr />
<gl-form class="common-note-form">
<div class="form-group row">
<div class="col-form-label col-sm-2">
<label for="epic-title">{{ __('Title') }}</label>
</div>
<div class="col-sm-10">
<gl-form class="common-note-form" @submit="save">
<gl-form-group :label="__('Title')" label-for="epic-title">
<gl-form-input
id="epic-title"
v-model="title"
:placeholder="__('Title')"
:placeholder="__('Enter a title for your epic')"
autocomplete="off"
autofocus
/>
</div>
</div>
<div class="form-group row">
<div class="col-form-label col-sm-2">
<label for="epic-description">{{ __('Description') }}</label>
</div>
<div class="col-sm-10">
</gl-form-group>
<gl-form-group :label="__('Description')" label-for="epic-description">
<markdown-field
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
......@@ -162,25 +161,18 @@ export default {
</textarea>
</template>
</markdown-field>
</div>
</div>
<div class="form-group row gl-mt-7">
<div class="col-sm-10 offset-sm-2">
<gl-form-checkbox v-model="confidential" data-testid="epic-confidentiality">{{
</gl-form-group>
<gl-form-group :label="__('Confidentiality')" label-for="epic-confidentiality">
<gl-form-checkbox id="epic-confidentiality" v-model="confidential">{{
__(
'This epic and any containing child epics are confidential and should only be visible to team members with at least Reporter access.',
'This epic and any containing child epics are confidential' +
' and should only be visible to team members' +
' with at least Reporter access.',
)
}}</gl-form-checkbox>
</div>
</div>
</gl-form-group>
<hr />
<div class="row">
<div class="col-lg-6">
<div class="form-group row">
<div class="col-form-label col-md-2 col-lg-4">
<label>{{ __('Labels') }}</label>
</div>
<div class="col-md-8 col-sm-10">
<gl-form-group :label="__('Labels')">
<div class="issuable-form-select-holder">
<labels-select-vue
:allow-label-edit="false"
......@@ -194,76 +186,69 @@ export default {
:labels-manage-path="groupUrl('labels')"
:labels-filter-base-path="groupUrl('epics')"
:labels-list-title="__('Select label')"
:dropdown-button-text="__('Labels')"
:dropdown-button-text="__('Choose labels')"
variant="embedded"
class="block labels js-labels-block"
@updateSelectedLabels="handleUpdateSelectedLabels"
>{{ __('None') }}</labels-select-vue
>
{{ __('None') }}
</labels-select-vue>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="form-group row">
<div class="col-form-label col-md-2 col-lg-4">
<label>{{ __('Start date') }}</label>
</div>
<div class="col-md-8 col-sm-10">
<div class="issuable-form-select-holder gl-mr-2">
</gl-form-group>
<gl-form-group
:label="__('Start date')"
:description="__('Leave empty to inherit from milestone dates')"
>
<div class="gl-display-inline-block gl-mr-2">
<gl-datepicker v-model="startDateFixed" data-testid="epic-start-date" />
</div>
<a
<gl-button
v-show="startDateFixed"
variant="link"
class="gl-white-space-nowrap"
data-testid="clear-start-date"
href="#"
@click="updateStartDate(null)"
>{{ __('Clear start date') }}</a
>
<span class="block gl-line-height-normal gl-mt-3 gl-text-gray-500">{{
__('Leave empty to inherit from milestone dates')
}}</span>
</div>
</div>
<div class="form-group row">
<div class="col-form-label col-md-2 col-lg-4">
<label>{{ __('Due Date') }}</label>
</div>
<div class="col-md-8 col-sm-10">
<div class="issuable-form-select-holder gl-mr-2">
{{ __('Clear start date') }}
</gl-button>
</gl-form-group>
<gl-form-group
:label="__('Due date')"
:description="__('Leave empty to inherit from milestone dates')"
>
<div class="gl-display-inline-block gl-mr-2">
<gl-datepicker v-model="dueDateFixed" data-testid="epic-due-date" />
</div>
<a
<gl-button
v-show="dueDateFixed"
variant="link"
class="gl-white-space-nowrap"
data-testid="clear-due-date"
href="#"
@click="updateDueDate(null)"
>{{ __('Clear due date') }}</a
>
<span class="block gl-line-height-normal gl-mt-3 gl-text-gray-500">{{
__('Leave empty to inherit from milestone dates')
}}</span>
</div>
</div>
</div>
</div>
</gl-form>
{{ __('Clear due date') }}
</gl-button>
</gl-form-group>
<div class="footer-block row-content-block gl-display-flex">
<gl-button
:loading="loading"
data-testid="save-epic"
type="submit"
variant="success"
:loading="loading"
:disabled="!title"
@click="save"
data-testid="save-epic"
>
{{ __('Create epic') }}
</gl-button>
<gl-button class="gl-ml-auto" data-testid="cancel-epic" :href="groupEpicsPath">{{
__('Cancel')
}}</gl-button>
<gl-button
type="button"
class="gl-ml-auto"
data-testid="cancel-epic"
:href="groupEpicsPath"
>
{{ __('Cancel') }}
</gl-button>
</div>
</gl-form>
</div>
</template>
......@@ -97,6 +97,10 @@
}
}
.issuable-form-select-holder {
width: $gl-dropdown-width;
}
.labels-select-wrapper.is-embedded {
.labels-select-dropdown-button {
@include gl-bg-white;
......@@ -130,6 +134,7 @@
bottom: 100%;
width: 300px !important;
max-height: none;
margin-bottom: $gl-spacing-scale-6 !important;
a:not(.btn) {
......@@ -137,6 +142,11 @@
}
}
.dropdown-title {
padding-top: $gl-spacing-scale-2 !important;
padding-bottom: $gl-spacing-scale-4 !important;
}
.dropdown-footer .list-unstyled {
@include gl-m-0;
}
......
......@@ -41,7 +41,7 @@ describe('ee/epic/components/epic_form.vue', () => {
const findTitle = () => wrapper.find('#epic-title');
const findDescription = () => wrapper.find('#epic-description');
const findLabels = () => wrapper.find(LabelsSelectVue);
const findConfidentialityCheck = () => wrapper.find('[data-testid="epic-confidentiality"]');
const findConfidentialityCheck = () => wrapper.find('#epic-confidentiality');
const findStartDate = () => wrapper.find('[data-testid="epic-start-date"]');
const findStartDateReset = () => wrapper.find('[data-testid="clear-start-date"]');
const findDueDate = () => wrapper.find('[data-testid="epic-due-date"]');
......@@ -75,14 +75,16 @@ describe('ee/epic/components/epic_form.vue', () => {
expect(wrapper.vm[field]).toBeTruthy();
findResetter().trigger('click');
findResetter().vm.$emit('click');
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm[field]).toBe(null);
});
});
});
describe('save', () => {
it('submits successfully if form data is provided', () => {
it('submits successfully if form data is provided', async () => {
createWrapper();
const addLabelIds = [1];
......@@ -101,7 +103,7 @@ describe('ee/epic/components/epic_form.vue', () => {
findStartDate().vm.$emit('input', startDateFixed);
findDueDate().vm.$emit('input', dueDateFixed);
findSaveButton().vm.$emit('click');
wrapper.vm.save();
expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
mutation: createEpic,
......@@ -122,18 +124,18 @@ describe('ee/epic/components/epic_form.vue', () => {
});
it.each`
status | result
${'succeeds'} | ${TEST_NEW_EPIC}
${'fails'} | ${TEST_FAILED}
`('resets loading indicator when $status', ({ result }) => {
status | result | loading
${'succeeds'} | ${TEST_NEW_EPIC} | ${true}
${'fails'} | ${TEST_FAILED} | ${false}
`('resets loading indicator when $status', ({ result, loading }) => {
createWrapper({ mutationResult: result });
const savePromise = wrapper.vm.save();
expect(wrapper.vm.loading).toBeTruthy();
expect(wrapper.vm.loading).toBe(true);
return savePromise.then(() => {
expect(findSaveButton().props('loading')).toBe(false);
expect(findSaveButton().props('loading')).toBe(loading);
});
});
});
......
......@@ -4598,6 +4598,9 @@ msgstr ""
msgid "Choose file…"
msgstr ""
msgid "Choose labels"
msgstr ""
msgid "Choose the top-level group for your repository imports."
msgstr ""
......@@ -8868,6 +8871,9 @@ msgstr ""
msgid "Enter a number"
msgstr ""
msgid "Enter a title for your epic"
msgstr ""
msgid "Enter a whole number between 0 and 100"
msgstr ""
......@@ -20966,6 +20972,9 @@ msgstr ""
msgid "Select health status"
msgstr ""
msgid "Select label"
msgstr ""
msgid "Select labels"
msgstr ""
......
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