Show reserved names in agenda view with better scheduler
closes CNVS-32183 Test Plan: - Set up an appointment group and limit the signups to 6 students - Add students to the appointment group - As a teacher, look at the agenda view - It should show all the students like: "Banner, Bruce; Lang, Scott; Parker, Peter; Rogers, Steve; Stark, Tony" when there are 5 or fewer people signed up - When there are more than 5 is should look like: "Banner, Bruce; Lang, Scott; Parker, Peter; Rogers, Steve; Stark, Tony; and more..." - Please note that it should also convey the status of the appointment group as a whole prior to listing attendees. For instance, X more available should show whenever there are still slots remaining or Filled when all the slots are taken - If no one has reserved any slots it should show "X Available" rather than "X more available" Change-Id: I00e85bf0886a9105abdb1d7bb8d08fe60e0b9f62 Reviewed-on: https://gerrit.instructure.com/91303 Tested-by: Jenkins Reviewed-by: Steven Burnett <sburnett@instructure.com> QA-Review: Heath Hales <hhales@instructure.com> Product-Review: Clay Diffrient <cdiffrient@instructure.com>
This commit is contained in:
parent
eabe8f26a2
commit
484025dee6
|
@ -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)
|
||||
|
|
|
@ -18,7 +18,11 @@
|
|||
<span class="screenreader-only">{{readableType}},</span>
|
||||
<i class="icon-{{iconType}}"></i>
|
||||
{{#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}}
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue