Commit c5f8a7df authored by Phil Hughes's avatar Phil Hughes

Merge branch '7103-show-milestone-dates-within-tooltips' into 'master'

Show actual Milestone dates within tooltips for Milestones in Epics sidebar

Closes #7103

See merge request gitlab-org/gitlab-ee!8048
parents 5ba9095b cbd67f5a
......@@ -61,7 +61,7 @@
const dateWords = dateInWords(date, true);
const parsedDateWords = dateWords ? dateWords.replace(',', '') : dateWords;
return date ? parsedDateWords : 'None';
return date ? parsedDateWords : __('None');
},
tooltipText(dateType = 'min') {
const defaultText = dateType === 'min' ? __('Start date') : __('Due date');
......@@ -72,7 +72,10 @@
`(${timeAgo})`,
].join(' ') : '';
return [defaultText, dateText].join('<br />');
if (date) {
return [defaultText, dateText].join('<br />');
}
return __('Start and due date');
},
},
};
......
......@@ -6,7 +6,7 @@ import EpicShowApp from './components/epic_show_app.vue';
export default () => {
const el = document.querySelector('#epic-show-app');
const metaData = convertObjectPropsToCamelCase(JSON.parse(el.dataset.meta));
const metaData = convertObjectPropsToCamelCase(JSON.parse(el.dataset.meta), { deep: true });
const initialData = JSON.parse(el.dataset.initial);
// Collapse the sidebar on mobile screens by default
......@@ -22,8 +22,9 @@ export default () => {
components: {
'epic-show-app': EpicShowApp,
},
render: createElement => createElement('epic-show-app', {
props,
}),
render: createElement =>
createElement('epic-show-app', {
props,
}),
});
};
......@@ -6,6 +6,7 @@ import Cookies from 'js-cookie';
import flash from '~/flash';
import { __, s__, sprintf } from '~/locale';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { dateInWords, parsePikadayDate } from '~/lib/utils/datetime_utility';
import ListLabel from '~/vue_shared/models/label';
import SidebarTodo from '~/sidebar/components/todo_toggle/todo.vue';
import SidebarCollapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
......@@ -85,11 +86,19 @@ export default {
required: false,
default: '',
},
startDateSourcingMilestoneDates: {
type: Object,
required: true,
},
dueDateSourcingMilestoneTitle: {
type: String,
required: false,
default: '',
},
dueDateSourcingMilestoneDates: {
type: Object,
required: true,
},
initialLabels: {
type: Array,
required: true,
......@@ -233,17 +242,33 @@ export default {
getDateTypeString(dateType) {
return dateType === DateTypes.start ? s__('Epics|start') : s__('Epics|due');
},
getDateFromMilestonesTooltip(dateType = 'start') {
getDateFromMilestonesTooltip(dateType = DateTypes.start) {
const { startDateTimeFromMilestones, dueDateTimeFromMilestones } = this.store;
const dateSourcingMilestoneTitle = this[`${dateType}DateSourcingMilestoneTitle`];
const sourcingMilestoneDates =
dateType === DateTypes.start
? this.startDateSourcingMilestoneDates
: this.dueDateSourcingMilestoneDates;
if (startDateTimeFromMilestones && dueDateTimeFromMilestones) {
return dateSourcingMilestoneTitle;
const startDate = parsePikadayDate(sourcingMilestoneDates.startDate);
const dueDate = parsePikadayDate(sourcingMilestoneDates.dueDate);
return `${dateSourcingMilestoneTitle}<br/><span class="text-tertiary">${dateInWords(
startDate,
true,
startDate.getFullYear() === dueDate.getFullYear(),
)}${dateInWords(dueDate, true)}</span>`;
}
return sprintf(s__('Epics|To schedule your epic\'s %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic.'), {
epicDateType: this.getDateTypeString(dateType),
});
return sprintf(
s__(
"Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic.",
),
{
epicDateType: this.getDateTypeString(dateType),
},
);
},
toggleSidebar() {
this.collapsed = !this.collapsed;
......@@ -293,9 +318,11 @@ export default {
})
.catch(() => {
this[savingBoolean] = false;
flash(sprintf(s__('Epics|An error occurred while saving %{epicDateType} date'), {
epicDateType: this.getDateTypeString(dateType),
}));
flash(
sprintf(s__('Epics|An error occurred while saving %{epicDateType} date'), {
epicDateType: this.getDateTypeString(dateType),
}),
);
});
},
changeStartDateType(dateTypeIsFixed, typeChangeOnEdit) {
......
......@@ -20,11 +20,19 @@ module EpicsHelper
start_date_fixed: epic.start_date_fixed,
start_date_from_milestones: epic.start_date_from_milestones,
start_date_sourcing_milestone_title: epic.start_date_sourcing_milestone&.title,
start_date_sourcing_milestone_dates: {
start_date: epic.start_date_sourcing_milestone&.start_date,
due_date: epic.start_date_sourcing_milestone&.due_date
},
due_date: epic.due_date,
due_date_is_fixed: epic.due_date_is_fixed?,
due_date_fixed: epic.due_date_fixed,
due_date_from_milestones: epic.due_date_from_milestones,
due_date_sourcing_milestone_title: epic.due_date_sourcing_milestone&.title,
due_date_sourcing_milestone_dates: {
start_date: epic.due_date_sourcing_milestone&.start_date,
due_date: epic.due_date_sourcing_milestone&.due_date
},
end_date: epic.end_date,
state: epic.state
}
......
---
title: Show actual Milestone dates within tooltips for Milestones in Epics sidebar
merge_request: 8048
author:
type: added
......@@ -5,14 +5,15 @@ describe EpicsHelper do
describe '#epic_show_app_data' do
let(:user) { create(:user) }
let(:milestone) { create(:milestone, title: 'make me a sandwich') }
let(:milestone1) { create(:milestone, title: 'make me a sandwich', start_date: '2010-01-01', due_date: '2019-12-31') }
let(:milestone2) { create(:milestone, title: 'make me a pizza', start_date: '2020-01-01', due_date: '2029-12-31') }
let!(:epic) do
create(
:epic,
author: user,
start_date_sourcing_milestone: milestone,
start_date_sourcing_milestone: milestone1,
start_date: Date.new(2000, 1, 1),
due_date_sourcing_milestone: milestone,
due_date_sourcing_milestone: milestone2,
due_date: Date.new(2000, 1, 2)
)
end
......@@ -32,6 +33,7 @@ describe EpicsHelper do
created author epic_id todo_exists todo_path state
start_date start_date_fixed start_date_is_fixed start_date_from_milestones start_date_sourcing_milestone_title
end_date due_date due_date_fixed due_date_is_fixed due_date_from_milestones due_date_sourcing_milestone_title
start_date_sourcing_milestone_dates due_date_sourcing_milestone_dates
])
expect(meta_data['author']).to eq({
'name' => user.name,
......@@ -40,9 +42,13 @@ describe EpicsHelper do
'src' => 'icon_path'
})
expect(meta_data['start_date']).to eq('2000-01-01')
expect(meta_data['start_date_sourcing_milestone_title']).to eq(milestone.title)
expect(meta_data['start_date_sourcing_milestone_title']).to eq(milestone1.title)
expect(meta_data['start_date_sourcing_milestone_dates']['start_date']).to eq(milestone1.start_date.to_s)
expect(meta_data['start_date_sourcing_milestone_dates']['due_date']).to eq(milestone1.due_date.to_s)
expect(meta_data['due_date']).to eq('2000-01-02')
expect(meta_data['due_date_sourcing_milestone_title']).to eq(milestone.title)
expect(meta_data['due_date_sourcing_milestone_title']).to eq(milestone2.title)
expect(meta_data['due_date_sourcing_milestone_dates']['start_date']).to eq(milestone2.start_date.to_s)
expect(meta_data['due_date_sourcing_milestone_dates']['due_date']).to eq(milestone2.due_date.to_s)
end
context 'when a user can update an epic' do
......@@ -52,9 +58,9 @@ describe EpicsHelper do
create(
:epic,
author: user,
start_date_sourcing_milestone: milestone,
start_date_sourcing_milestone: milestone1,
start_date: Date.new(2000, 1, 1),
due_date_sourcing_milestone: milestone,
due_date_sourcing_milestone: milestone2,
due_date: Date.new(2000, 1, 2)
)
end
......@@ -71,11 +77,12 @@ describe EpicsHelper do
created author epic_id todo_exists todo_path state
start_date start_date_fixed start_date_is_fixed start_date_from_milestones start_date_sourcing_milestone_title
end_date due_date due_date_fixed due_date_is_fixed due_date_from_milestones due_date_sourcing_milestone_title
start_date_sourcing_milestone_dates due_date_sourcing_milestone_dates
])
expect(meta_data['start_date']).to eq('2000-01-01')
expect(meta_data['start_date_sourcing_milestone_title']).to eq(milestone.title)
expect(meta_data['start_date_sourcing_milestone_title']).to eq(milestone1.title)
expect(meta_data['due_date']).to eq('2000-01-02')
expect(meta_data['due_date_sourcing_milestone_title']).to eq(milestone.title)
expect(meta_data['due_date_sourcing_milestone_title']).to eq(milestone2.title)
end
end
end
......
......@@ -57,7 +57,15 @@ export const contentProps = {
dueDateIsFixed: true,
dueDateFromMilestones: '',
startDateSourcingMilestoneTitle: 'Milestone for Start Date',
startDateSourcingMilestoneDates: {
startDate: '2010-01-01',
dueDate: '2019-12-31',
},
dueDateSourcingMilestoneTitle: 'Milestone for End Date',
dueDateSourcingMilestoneDates: {
startDate: '2020-01-01',
dueDate: '2029-12-31',
},
labels: mockLabels,
participants: mockParticipants,
subscribed: true,
......
......@@ -32,7 +32,9 @@ describe('epicSidebar', () => {
dueDateFixed,
dueDateFromMilestones,
startDateSourcingMilestoneTitle,
startDateSourcingMilestoneDates,
dueDateSourcingMilestoneTitle,
dueDateSourcingMilestoneDates,
} = props;
const defaultPropsData = {
......@@ -50,7 +52,9 @@ describe('epicSidebar', () => {
dueDateFromMilestones,
updatePath: updateEndpoint,
startDateSourcingMilestoneTitle,
startDateSourcingMilestoneDates,
dueDateSourcingMilestoneTitle,
dueDateSourcingMilestoneDates,
toggleSubscriptionPath,
labelsPath,
labelsWebUrl,
......@@ -174,6 +178,44 @@ describe('epicSidebar', () => {
it('returns tooltip string for milestone', () => {
expect(vm.getDateFromMilestonesTooltip('start')).toBe('To schedule your epic\'s start date based on milestones, assign a milestone with a start date to any issue in the epic.');
});
it('returns tooltip string with milestone dates', () => {
const vmDatesFromMilestones = mountComponent(
EpicSidebar,
Object.assign({}, defaultPropsData, {
startDateFromMilestones: startDateSourcingMilestoneDates.startDate,
dueDateFromMilestones: dueDateSourcingMilestoneDates.dueDate,
})
);
expect(vmDatesFromMilestones.getDateFromMilestonesTooltip('start')).toBe('Milestone for Start Date<br/><span class="text-tertiary">Jan 1, 2010 – Dec 31, 2019</span>');
vmDatesFromMilestones.$destroy();
});
it('returns tooltip string with milestone dates when dates are from same year', () => {
const startDate = '2018-01-01';
const dueDate = '2018-03-31';
const vmDatesFromMilestones = mountComponent(
EpicSidebar,
Object.assign({}, defaultPropsData, {
startDateSourcingMilestoneDates: {
startDate,
dueDate,
},
dueDateSourcingMilestoneDates: {
startDate,
dueDate,
},
startDateFromMilestones: startDate,
dueDateFromMilestones: dueDate,
})
);
expect(vmDatesFromMilestones.getDateFromMilestonesTooltip('start')).toBe('Milestone for Start Date<br/><span class="text-tertiary">Jan 1 – Mar 31, 2018</span>');
vmDatesFromMilestones.$destroy();
});
});
describe('toggleSidebar', () => {
......
......@@ -7458,6 +7458,9 @@ msgstr ""
msgid "Start a review"
msgstr ""
msgid "Start and due date"
msgstr ""
msgid "Start date"
msgstr ""
......
......@@ -76,5 +76,11 @@ describe('collapsedGroupedDatePicker', () => {
expect(icons.length).toEqual(1);
expect(icons[0].innerText.trim()).toEqual('None');
});
it('should have tooltip as `Start and due dates`', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
expect(icons[0].dataset.originalTitle).toBe('Start and due date');
});
});
});
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