Commit a3982e3c authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch 'psi-iteration-date-smarts' into 'master'

Prefill iteration date with sensible value

See merge request gitlab-org/gitlab!72165
parents 38bbc861 efac77f3
......@@ -2,12 +2,16 @@
import { GlAlert, GlButton, GlForm, GlFormInput } from '@gitlab/ui';
import initDatePicker from '~/behaviors/date_picker';
import createFlash from '~/flash';
import { dayAfter, formatDate } from '~/lib/utils/datetime_utility';
import { TYPE_ITERATIONS_CADENCE } from '~/graphql_shared/constants';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __, s__ } from '~/locale';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
import readIteration from '../queries/iteration.query.graphql';
import createIteration from '../queries/iteration_create.mutation.graphql';
import readCadence from '../queries/iteration_cadence.query.graphql';
import updateIteration from '../queries/update_iteration.mutation.graphql';
import iterationsInCadence from '../queries/group_iterations_in_cadence.query.graphql';
export default {
cadencesList: {
......@@ -40,13 +44,15 @@ export default {
if (!iteration) {
this.error = s__('Iterations|Unable to find iteration.');
return;
return null;
}
this.title = iteration.title;
this.description = iteration.description;
this.startDate = iteration.startDate;
this.dueDate = iteration.dueDate;
return iteration;
},
error(err) {
this.error = err.message;
......@@ -59,6 +65,7 @@ export default {
loading: false,
error: '',
group: { iteration: {} },
cadence: {},
title: '',
description: '',
startDate: '',
......@@ -85,9 +92,51 @@ export default {
};
},
},
mounted() {
async mounted() {
// TODO: utilize GlDatepicker instead of relying on this jQuery behavior
initDatePicker();
// prefill start date for the New cadence form
// if there's iterations in the cadence, use last end_date + 1
// else use cadence startDate
if (!this.isEditing && this.cadenceId) {
const { data } = await this.$apollo.query({
query: iterationsInCadence,
variables: {
fullPath: this.fullPath,
iterationCadenceId: convertToGraphQLId(TYPE_ITERATIONS_CADENCE, this.cadenceId),
lastPageSize: 1,
state: 'all',
},
});
const iteration = data.workspace.iterations?.nodes[0];
if (iteration) {
this.startDate = formatDate(
dayAfter(new Date(iteration.dueDate), { utc: true }),
'yyyy-mm-dd',
);
} else {
const { data: cadenceData } = await this.$apollo.query({
query: readCadence,
variables: {
fullPath: this.fullPath,
id: this.cadenceId,
},
});
if (cadenceData.group) {
const cadence = cadenceData.group?.iterationCadences?.nodes[0];
if (!cadence) {
this.error = s__('Iterations|Unable to find iteration cadence.');
return;
}
this.startDate = cadence.startDate;
}
}
}
},
methods: {
save() {
......
......@@ -9,6 +9,7 @@ import createMockApollo from 'helpers/mock_apollo_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { manualIterationCadence } from '../mock_data';
const push = jest.fn();
const $router = {
......@@ -28,17 +29,7 @@ describe('Iteration cadence form', () => {
let wrapper;
const groupPath = 'gitlab-org';
const id = 72;
const iterationCadence = {
id: `gid://gitlab/Iterations::Cadence/${id}`,
title: 'An iteration',
automatic: true,
rollOver: false,
durationInWeeks: '3',
description: 'The words',
duration: '3',
startDate: '2020-06-28',
iterationsInAdvance: '2',
};
const iterationCadence = manualIterationCadence;
const createMutationSuccess = {
data: { result: { iterationCadence, errors: [] } },
......@@ -53,7 +44,7 @@ describe('Iteration cadence form', () => {
group: {
id: 'gid://gitlab/Group/114',
iterationCadences: {
nodes: [iterationCadence],
nodes: [manualIterationCadence],
},
},
},
......
......@@ -5,13 +5,29 @@ import IterationForm from 'ee/iterations/components/iteration_form.vue';
import readIteration from 'ee/iterations/queries/iteration.query.graphql';
import createIteration from 'ee/iterations/queries/iteration_create.mutation.graphql';
import updateIteration from 'ee/iterations/queries/update_iteration.mutation.graphql';
import groupIterationsInCadenceQuery from 'ee/iterations/queries/group_iterations_in_cadence.query.graphql';
import readCadence from 'ee/iterations/queries/iteration_cadence.query.graphql';
import createRouter from 'ee/iterations/router';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { dayAfter, formatDate } from '~/lib/utils/datetime_utility';
import {
manualIterationCadence as cadence,
mockGroupIterations,
mockIterationNode as iteration,
createMutationSuccess,
createMutationFailure,
updateMutationSuccess,
emptyGroupIterationsSuccess,
nonEmptyGroupIterationsSuccess,
readCadenceSuccess,
} from '../mock_data';
const baseUrl = '/cadences/';
const iterationId = getIdFromGraphQLId(iteration.id);
const cadenceId = getIdFromGraphQLId(cadence.id);
function createMockApolloProvider(requestHandlers) {
Vue.use(VueApollo);
......@@ -23,41 +39,20 @@ describe('Iteration Form', () => {
let wrapper;
let router;
const groupPath = 'gitlab-org';
const iterationId = 72;
const cadenceId = 2;
const iteration = {
id: `gid://gitlab/Iteration/${iterationId}`,
iid: 70,
title: 'An iteration',
state: 'opened',
webPath: '/test',
description: 'The words',
descriptionHtml: '<p>The words</p>',
startDate: '2020-06-28',
dueDate: '2020-07-05',
};
const readMutationSuccess = {
data: {
group: { id: 'gid://gitlab/Group/114', iterations: { nodes: [iteration] }, errors: [] },
},
};
const createMutationSuccess = { data: { iterationCreate: { iteration, errors: [] } } };
const createMutationFailure = {
data: { iterationCreate: { iteration, errors: ['alas, your data is unchanged'] } },
};
const updateMutationSuccess = { data: { updateIteration: { iteration, errors: [] } } };
function createComponent({
mutationQuery = createIteration,
mutationResult = createMutationSuccess,
query = readIteration,
result = readMutationSuccess,
result = mockGroupIterations,
resolverMock = jest.fn().mockResolvedValue(mutationResult),
groupIterationsSuccess = emptyGroupIterationsSuccess,
} = {}) {
const apolloProvider = createMockApolloProvider([
[query, jest.fn().mockResolvedValue(result)],
[mutationQuery, resolverMock],
[groupIterationsInCadenceQuery, jest.fn().mockResolvedValue(groupIterationsSuccess)],
[readCadence, jest.fn().mockResolvedValue(readCadenceSuccess)],
]);
wrapper = extendedWrapper(
mount(IterationForm, {
......@@ -95,7 +90,10 @@ describe('Iteration Form', () => {
const resolverMock = jest.fn().mockResolvedValue(createMutationSuccess);
beforeEach(() => {
router.replace({ name: 'newIteration', params: { cadenceId, iterationId: undefined } });
router.replace({
name: 'newIteration',
params: { cadenceId, iterationId: undefined },
});
createComponent({ resolverMock });
});
......@@ -126,7 +124,7 @@ describe('Iteration Form', () => {
groupPath,
title,
description,
iterationsCadenceId: convertToGraphQLId('Iterations::Cadence', cadenceId),
iterationsCadenceId: convertToGraphQLId('Iterations::Cadence', cadence.id),
startDate,
dueDate,
},
......@@ -159,11 +157,49 @@ describe('Iteration Form', () => {
});
});
});
describe('prefill start date field', () => {
describe('cadence with iterations', () => {
it('starts next day after the last iteration', async () => {
await createComponent({
groupIterationsSuccess: nonEmptyGroupIterationsSuccess,
});
await waitForPromises();
const expectedDate = formatDate(
dayAfter(new Date(iteration.dueDate), { utc: true }),
'yyyy-mm-dd',
);
expect(findStartDate().element.value).toBe(expectedDate);
});
});
describe('manual cadence without iterations', () => {
beforeEach(async () => {
await createComponent({
groupIterationsSuccess: emptyGroupIterationsSuccess,
});
await nextTick();
});
it('uses cadence start date', () => {
const expectedDate = cadence.startDate;
expect(findStartDate().element.value).toBe(expectedDate);
});
});
});
});
describe('Edit iteration', () => {
beforeEach(() => {
router.replace({ name: 'editIteration', params: { cadenceId, iterationId } });
router.replace({
name: 'editIteration',
params: { cadenceId: cadence.id, iterationId: iteration.id },
});
});
afterEach(() => {
......@@ -212,7 +248,7 @@ describe('Iteration Form', () => {
expect(resolverMock).toHaveBeenCalledWith({
input: {
groupPath,
id: iterationId,
id: iteration.id,
title,
description,
startDate,
......@@ -236,7 +272,7 @@ describe('Iteration Form', () => {
expect(resolverMock).toHaveBeenCalledWith({
input: {
groupPath,
id: iterationId,
id: iteration.id,
startDate: '',
dueDate: '',
title: '',
......
......@@ -36,3 +36,78 @@ export const mockProjectIterations = {
},
},
};
export const manualIterationCadence = {
id: `gid://gitlab/Iterations::Cadence/72`,
title: 'A manual iteration cadence',
automatic: true,
rollOver: false,
durationInWeeks: '3',
description: 'The words',
duration: '3',
startDate: '2020-06-28',
iterationsInAdvance: '2',
};
export const createMutationSuccess = {
data: { iterationCreate: { iteration: mockIterationNode, errors: [] } },
};
export const createMutationFailure = {
data: {
iterationCreate: { iteration: mockIterationNode, errors: ['alas, your data is unchanged'] },
},
};
export const updateMutationSuccess = {
data: { updateIteration: { iteration: mockIterationNode, errors: [] } },
};
export const emptyGroupIterationsSuccess = {
data: {
workspace: {
id: 'gid://gitlab/Group/114',
iterations: {
nodes: [],
pageInfo: {
hasNextPage: false,
hasPreviousPage: false,
startCursor: '',
endCursor: '',
},
},
},
},
};
export const nonEmptyGroupIterationsSuccess = {
data: {
workspace: {
id: 1,
iterations: {
nodes: [
{
...mockIterationNode,
scopedPath: '/',
},
],
pageInfo: {
hasNextPage: false,
hasPreviousPage: false,
startCursor: '',
endCursor: '',
},
},
},
},
};
export const readCadenceSuccess = {
data: {
group: {
id: 'gid://gitlab/Group/114',
iterationCadences: {
nodes: [manualIterationCadence],
},
},
},
};
......@@ -19597,6 +19597,9 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
msgid "Iterations|Unable to find iteration cadence."
msgstr ""
msgid "Iterations|Unable to find iteration."
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