diff --git a/tailbone/static/js/tailbone.edit-shifts.js b/tailbone/static/js/tailbone.edit-shifts.js new file mode 100644 index 00000000..1593acd7 --- /dev/null +++ b/tailbone/static/js/tailbone.edit-shifts.js @@ -0,0 +1,186 @@ + +/************************************************************ + * + * tailbone.edit-shifts.js + * + * Common logic for editing time sheet / schedule data. + * + ************************************************************/ + + +var editing_day = null; +var new_shift_id = 1; + +function add_shift(focus, uuid, start_time, end_time) { + var shift = $('#snippets .shift').clone(); + if (! uuid) { + uuid = 'new-' + (new_shift_id++).toString(); + } + shift.attr('data-uuid', uuid); + shift.children('input').each(function() { + var name = $(this).attr('name') + '-' + uuid; + $(this).attr('name', name); + $(this).attr('id', name); + }); + shift.children('input[name|="edit_start_time"]').val(start_time || ''); + shift.children('input[name|="edit_end_time"]').val(end_time || ''); + $('#day-editor .shifts').append(shift); + shift.children('input').timepicker({showPeriod: true}); + if (focus) { + shift.children('input:first').focus(); + } +} + +function calc_minutes(start_time, end_time) { + var start = parseTime(start_time); + start = new Date(2000, 0, 1, start.hh, start.mm); + var end = parseTime(end_time); + end = new Date(2000, 0, 1, end.hh, end.mm); + return Math.floor((end - start) / 1000 / 60); +} + +function format_minutes(minutes) { + var hours = Math.floor(minutes / 60); + if (hours) { + minutes -= hours * 60; + } + return hours.toString() + ':' + (minutes < 10 ? '0' : '') + minutes.toString(); +} + +// stolen from http://stackoverflow.com/a/1788084 +function parseTime(s) { + var part = s.match(/(\d+):(\d+)(?: )?(am|pm)?/i); + var hh = parseInt(part[1], 10); + var mm = parseInt(part[2], 10); + var ap = part[3] ? part[3].toUpperCase() : null; + if (ap == 'AM') { + if (hh == 12) { + hh = 0; + } + } else if (ap == 'PM') { + if (hh != 12) { + hh += 12; + } + } + return { hh: hh, mm: mm }; +} + +function time_input(shift, type) { + var input = shift.children('input[name|="' + type + '_time"]'); + if (! input.length) { + input = $(''); + shift.append(input); + } + return input; +} + +function update_row_hours(row) { + var minutes = 0; + row.find('.day .shift:not(.deleted)').each(function() { + var time_range = $.trim($(this).children('span').text()).split(' - '); + minutes += calc_minutes(time_range[0], time_range[1]); + }); + row.children('.total').text(minutes ? format_minutes(minutes) : '0'); +} + +$(function() { + + $('.timesheet').on('click', '.day', function() { + editing_day = $(this); + var editor = $('#day-editor'); + var employee = editing_day.siblings('.employee').text(); + var date = weekdays[editing_day.get(0).cellIndex - 1]; + var shifts = editor.children('.shifts'); + shifts.empty(); + editing_day.children('.shift:not(.deleted)').each(function() { + var uuid = $(this).data('uuid'); + var time_range = $.trim($(this).children('span').text()).split(' - '); + add_shift(false, uuid, time_range[0], time_range[1]); + }); + if (! shifts.children('.shift').length) { + add_shift(); + } + editor.dialog({ + modal: true, + title: employee + ' - ' + date, + position: {my: 'center', at: 'center', of: editing_day}, + width: 'auto', + autoResize: true, + buttons: [ + { + text: "Update", + click: function() { + + // TODO: need to validate times here... + + // create / update shifts in time table, as needed + editor.find('.shifts .shift').each(function() { + var uuid = $(this).data('uuid'); + var start_time = $(this).children('input[name|="edit_start_time"]').val(); + var end_time = $(this).children('input[name|="edit_end_time"]').val(); + var shift = editing_day.children('.shift[data-uuid="' + uuid + '"]'); + if (! shift.length) { + shift = $('
'); + shift.append($('')); + editing_day.append(shift); + } + shift.children('span').text(start_time + ' - ' + end_time); + time_input(shift, 'start').val(date + ' ' + start_time); + time_input(shift, 'end').val(date + ' ' + end_time); + }); + + // remove shifts from time table, as needed + editing_day.children('.shift').each(function() { + var uuid = $(this).data('uuid'); + if (! editor.find('.shifts .shift[data-uuid="' + uuid + '"]').length) { + if (uuid.match(/^new-/)) { + $(this).remove(); + } else { + $(this).addClass('deleted'); + $(this).append($('')); + } + } + }); + + // mark day as modified, close dialog + editing_day.addClass('modified'); + $('.save-changes').button('enable'); + $('.undo-changes').button('enable'); + update_row_hours(editing_day.parents('tr:first')); + editor.dialog('close'); + data_modified = true; + okay_to_leave = false; + } + }, + { + text: "Cancel", + click: function() { + editor.dialog('close'); + } + } + ] + }); + }); + + $('#day-editor #add-shift').click(function() { + add_shift(true); + }); + + $('#day-editor').on('click', '.shifts button', function() { + $(this).parents('.shift:first').remove(); + }); + + $('.save-changes').click(function() { + $(this).button('disable').button('option', 'label', "Saving Changes..."); + okay_to_leave = true; + $('#timetable-form').submit(); + }); + + $('.undo-changes').click(function() { + $(this).button('disable').button('option', 'label', "Refreshing..."); + okay_to_leave = true; + location.href = location.href; + }); + +}); diff --git a/tailbone/static/js/tailbone.js b/tailbone/static/js/tailbone.js index 7e3b952c..8169b7db 100644 --- a/tailbone/static/js/tailbone.js +++ b/tailbone/static/js/tailbone.js @@ -259,24 +259,6 @@ $(function() { }); - /* - * Whenever the "change" button is clicked within the context of an - * autocomplete field, hide the static display and show the autocomplete - * textbox. - */ - $('div.autocomplete-container button.autocomplete-change').click(function() { - var container = $(this).parents('div.autocomplete-container'); - var textbox = container.find('input.autocomplete-textbox'); - - container.find('input[type="hidden"]').val(''); - container.find('div.autocomplete-display').hide(); - - textbox.val(''); - textbox.show(); - textbox.select(); - textbox.focus(); - }); - /* * Add "check all" functionality to tables with checkboxes. */ diff --git a/tailbone/templates/autocomplete.mako b/tailbone/templates/autocomplete.mako index 341ad8bb..249f8f2e 100644 --- a/tailbone/templates/autocomplete.mako +++ b/tailbone/templates/autocomplete.mako @@ -1,6 +1,6 @@ ## -*- coding: utf-8 -*- ## TODO: This function signature is getting out of hand... -<%def name="autocomplete(field_name, service_url, field_value=None, field_display=None, width='300px', select=None, selected=None, cleared=None, options={})"> +<%def name="autocomplete(field_name, service_url, field_value=None, field_display=None, width='300px', select=None, selected=None, cleared=None, change_clicked=None, options={})">
+ ${render_shift(shift)} +
+ % endfor +%def> + +<%def name="edit_form()"> + ${h.form(url('timesheet.employee.edit'), id='timetable-form')} + ${h.csrf_token(request)} +%def> + +<%def name="edit_tools()"> + +%def> + +${timesheet_wrapper(edit_form=edit_form, edit_tools=edit_tools, context_menu=context_menu, render_day=render_day, change_employee='confirm_leave')} + +${edit_tools()} + + + +