diff --git a/app/coffeescripts/calendar/CommonEvent.CalendarEvent.coffee b/app/coffeescripts/calendar/CommonEvent.CalendarEvent.coffee index ebf1adda5c2..6756d6eb090 100644 --- a/app/coffeescripts/calendar/CommonEvent.CalendarEvent.coffee +++ b/app/coffeescripts/calendar/CommonEvent.CalendarEvent.coffee @@ -4,9 +4,10 @@ define [ 'compiled/util/fcUtil' 'compiled/util/semanticDateRange' 'compiled/calendar/CommonEvent' + 'compiled/util/natcompare' 'jquery.instructure_date_and_time' 'jquery.instructure_misc_helpers' -], (I18n, $, fcUtil, semanticDateRange, CommonEvent) -> +], (I18n, $, fcUtil, semanticDateRange, CommonEvent, natcompare) -> deleteConfirmation = I18n.t('prompts.delete_event', "Are you sure you want to delete this event?") @@ -15,6 +16,7 @@ define [ super data, contextInfo, actualContextInfo @eventType = 'calendar_event' @appointmentGroupEventStatus = @calculateAppointmentGroupEventStatus() + @reservedUsers = @getListOfReservedPeople(5).join('; ') @deleteConfirmation = deleteConfirmation @deleteURL = contextInfo.calendar_event_url @@ -94,12 +96,29 @@ define [ calculateAppointmentGroupEventStatus: -> status = I18n.t 'Available' - if @calendarEvent.available_slots > 0 status = I18n.t('%{availableSlots} Available', {availableSlots: @calendarEvent.available_slots}) + if @calendarEvent.available_slots > 0 && @calendarEvent.child_events?.length + status = I18n.t('%{availableSlots} more available', {availableSlots: @calendarEvent.available_slots}) if @calendarEvent.available_slots == 0 status = I18n.t('Filled') - if @calendarEvent.reserved == true || (@calendarEvent.appointment_group_url && @calendarEvent.parent_event_id) + if @consideredReserved() status = I18n.t('Reserved') status + + # Returns an array of sortable user names that have reserved this slot optionally + # limited to a certain number. The list is returned sorted naturally. If there + # are more than the limit 'and more...' will be appended. + getListOfReservedPeople: (limit) -> + return [] unless @calendarEvent.child_events?.length + names = @calendarEvent.child_events?.map((child_event) -> child_event.user?.sortable_name) + sorted = names.sort((a, b) => natcompare.strings(a, b)) + if (limit) + sorted = sorted.slice(0, limit) + if @calendarEvent.child_events?.length > limit + sorted.push(I18n.t('and more...')) + sorted + + # True if the slot should be considered reserved + consideredReserved: -> @calendarEvent.reserved == true || (@calendarEvent.appointment_group_url && @calendarEvent.parent_event_id) diff --git a/app/views/jst/calendar/agendaView.handlebars b/app/views/jst/calendar/agendaView.handlebars index dc740710e48..0a670bf2acb 100644 --- a/app/views/jst/calendar/agendaView.handlebars +++ b/app/views/jst/calendar/agendaView.handlebars @@ -18,7 +18,11 @@ {{readableType}}, {{#if ../../meta.better_scheduler}} - {{#truncate title 60}}{{/truncate}} - {{appointmentGroupEventStatus}} + {{#if can_edit}} + {{#truncate title 60}}{{/truncate}} - {{appointmentGroupEventStatus}} {{#if reservedUsers }} - {{reservedUsers}} {{/if}} + {{else}} + {{#truncate title 60}}{{/truncate}} - {{appointmentGroupEventStatus}} + {{/if}} {{else}} {{#ifAll ../../../meta.displayAppointmentEvents isAppointmentGroupEvent}} {{appointmentGroupEventStatus}} diff --git a/spec/javascripts/jsx/calendar/CommonEvent.CalendarEventSpec.jsx b/spec/javascripts/jsx/calendar/CommonEvent.CalendarEventSpec.jsx index 5cac4a404db..ae34b078c75 100644 --- a/spec/javascripts/jsx/calendar/CommonEvent.CalendarEventSpec.jsx +++ b/spec/javascripts/jsx/calendar/CommonEvent.CalendarEventSpec.jsx @@ -4,22 +4,64 @@ define([ let calendarEvent; + const getFakeChildEvents = () => { + return [ + { user: {sortable_name: 'Stark, Tony'}}, + { user: {sortable_name: 'Parker, Peter'}}, + { user: {sortable_name: 'Rogers, Steve'}} + ]; + } + module('CommonEvent.CalendarEvent', { setup () { - const data = {} - const contexts = ['course_1'] - calendarEvent = new CalendarEvent(data, contexts) + const data = { + child_events: [] + }; + const contexts = ['course_1']; + calendarEvent = new CalendarEvent(data, contexts); }, teardown () { calendarEvent = null; } }); - test('calculateAppointmentGroupEventStatus returns number of available slots string when more than 0', () => { + test('Constructor sets reservedUsers from child_events limited to 5 and joined by "; "', () => { + const data = { + child_events: getFakeChildEvents().concat([ + { user: {sortable_name: 'Banner, Bruce'}}, + { user: {sortable_name: 'Lang, Scott'}} + ]) + }; + calendarEvent = new CalendarEvent(data, ['course_1']); + const expected = "Banner, Bruce; Lang, Scott; Parker, Peter; Rogers, Steve; Stark, Tony"; + equal(calendarEvent.reservedUsers, expected); + }); + + test('Constructor sets reservedUsers from child_events limited to 5 and joined by "; " with "and more..." if more than 5', () => { + const data = { + child_events: getFakeChildEvents().concat([ + { user: {sortable_name: 'Banner, Bruce'}}, + { user: {sortable_name: 'Lang, Scott'}}, + { user: {sortable_name: 'Barton, Clint'}} + + ]) + }; + calendarEvent = new CalendarEvent(data, ['course_1']); + const expected = "Banner, Bruce; Barton, Clint; Lang, Scott; Parker, Peter; Rogers, Steve; and more..."; + equal(calendarEvent.reservedUsers, expected); + }); + + test('calculateAppointmentGroupEventStatus returns number of available slots string when more than 0 and none are reserved', () => { calendarEvent.calendarEvent.available_slots = 20; equal(calendarEvent.calculateAppointmentGroupEventStatus(), '20 Available'); }); + test('calculateAppointmentGroupEventStatus returns "X more available" when there are some reserved and some open', () => { + calendarEvent.calendarEvent.child_events = getFakeChildEvents(); + calendarEvent.calendarEvent.available_slots = 17; + equal(calendarEvent.calculateAppointmentGroupEventStatus(), '17 more available'); + }) + test('calculateAppointmentGroupEventStatus gives "Filled" string when 0 available_slots', () => { calendarEvent.calendarEvent.available_slots = 0; equal(calendarEvent.calculateAppointmentGroupEventStatus(), 'Filled'); @@ -37,5 +79,17 @@ define([ equal(calendarEvent.calculateAppointmentGroupEventStatus(), 'Reserved'); }); + test('consideredReserved returns true when reserve should be shown', () => { + calendarEvent.calendarEvent.reserved = true; + ok(calendarEvent.consideredReserved(), 'true when reserved'); + + calendarEvent.calendarEvent.reserved = false; + calendarEvent.calendarEvent.appointment_group_url = 1; + calendarEvent.calendarEvent.parent_event_id = 30; + ok(calendarEvent.consideredReserved(), 'true with appointment_group_url and parent_event_id'); + }); + + + })