Add speed bump when leaving timesheet page w/ unsaved changes
Also add save/undo buttons to top as well as bottom of timesheet.
This commit is contained in:
parent
e153390c15
commit
9e7cb532c8
|
@ -20,6 +20,10 @@
|
|||
width: auto;
|
||||
}
|
||||
|
||||
.timesheet-header td.filters .buttons {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.timesheet-header td.menu {
|
||||
padding: 0.5em;
|
||||
vertical-align: top;
|
||||
|
@ -46,7 +50,7 @@
|
|||
border-bottom: 1px solid black;
|
||||
border-right: 1px solid black;
|
||||
clear: both;
|
||||
margin-top: 0.3em;
|
||||
margin: 0.3em 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
@ -82,3 +86,11 @@
|
|||
.timesheet tbody tr.total {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/******************************
|
||||
* below timesheet...
|
||||
******************************/
|
||||
|
||||
div.buttons {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
|
|
@ -9,19 +9,51 @@
|
|||
${h.stylesheet_link(request.static_url('tailbone:static/css/timesheet.css'))}
|
||||
<script type="text/javascript">
|
||||
|
||||
var data_modified = false;
|
||||
var okay_to_leave = true;
|
||||
var previous_selections = {};
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
if (! okay_to_leave) {
|
||||
return "If you leave this page, you will lose all unsaved changes!";
|
||||
}
|
||||
}
|
||||
|
||||
function employee_selected(uuid, name) {
|
||||
$('.timesheet-wrapper form').submit();
|
||||
$('#filter-form').submit();
|
||||
}
|
||||
|
||||
function confirm_leave() {
|
||||
if (data_modified) {
|
||||
if (confirm("If you navigate away from this page now, you will lose " +
|
||||
"unsaved changes.\n\nAre you sure you wish to do this?")) {
|
||||
okay_to_leave = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
$('.timesheet-wrapper form').submit(function() {
|
||||
$('#filter-form').submit(function() {
|
||||
$('.timesheet-header').mask("Fetching data");
|
||||
});
|
||||
|
||||
$('.timesheet-header select').each(function() {
|
||||
previous_selections[$(this).attr('name')] = $(this).val();
|
||||
});
|
||||
|
||||
$('.timesheet-header select').selectmenu({
|
||||
change: function(event, ui) {
|
||||
$(ui.item.element).parents('form').submit();
|
||||
if (confirm_leave()) {
|
||||
$('#filter-form').submit();
|
||||
} else {
|
||||
var select = ui.item.element.parents('select');
|
||||
select.val(previous_selections[select.attr('name')]);
|
||||
select.selectmenu('refresh');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -30,7 +62,10 @@
|
|||
});
|
||||
|
||||
$('.week-picker button.nav').click(function() {
|
||||
$('.week-picker #date').val($(this).data('date'));
|
||||
if (confirm_leave()) {
|
||||
$('.week-picker #date').val($(this).data('date'));
|
||||
$('#filter-form').submit();
|
||||
}
|
||||
});
|
||||
|
||||
$('.week-picker #date').datepicker({
|
||||
|
@ -39,7 +74,7 @@
|
|||
changeMonth: true,
|
||||
showButtonPanel: true,
|
||||
onSelect: function(dateText, inst) {
|
||||
$(this).parents('form').submit();
|
||||
$('#filter-form').submit();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -50,7 +85,7 @@
|
|||
|
||||
<%def name="context_menu()"></%def>
|
||||
|
||||
<%def name="timesheet()">
|
||||
<%def name="timesheet(edit_form=None, edit_tools=None)">
|
||||
<style type="text/css">
|
||||
.timesheet thead th {
|
||||
width: ${'{:0.2f}'.format(100.0 / 9)}%;
|
||||
|
@ -59,7 +94,7 @@
|
|||
|
||||
<div class="timesheet-wrapper">
|
||||
|
||||
${form.begin()}
|
||||
${form.begin(id='filter-form')}
|
||||
|
||||
<table class="timesheet-header">
|
||||
<tbody>
|
||||
|
@ -99,6 +134,10 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
% if edit_tools:
|
||||
${edit_tools()}
|
||||
% endif
|
||||
|
||||
</td><!-- filters -->
|
||||
|
||||
<td class="menu">
|
||||
|
@ -112,8 +151,8 @@
|
|||
<td class="tools">
|
||||
<div class="grid-tools">
|
||||
<div class="week-picker">
|
||||
<button class="nav" data-date="${prev_sunday.strftime('%m/%d/%Y')}">« Previous</button>
|
||||
<button class="nav" data-date="${next_sunday.strftime('%m/%d/%Y')}">Next »</button>
|
||||
<button type="button" class="nav" data-date="${prev_sunday.strftime('%m/%d/%Y')}">« Previous</button>
|
||||
<button type="button" class="nav" data-date="${next_sunday.strftime('%m/%d/%Y')}">Next »</button>
|
||||
<label>Jump to week:</label>
|
||||
${form.text('date', value=sunday.strftime('%m/%d/%Y'))}
|
||||
</div>
|
||||
|
@ -126,6 +165,10 @@
|
|||
|
||||
${form.end()}
|
||||
|
||||
% if edit_form:
|
||||
${edit_form()}
|
||||
% endif
|
||||
|
||||
<table class="timesheet">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -167,6 +210,11 @@
|
|||
% endif
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
% if edit_form:
|
||||
${h.end_form()}
|
||||
% endif
|
||||
|
||||
</div><!-- timesheet-wrapper -->
|
||||
</%def>
|
||||
|
||||
|
|
|
@ -152,10 +152,12 @@
|
|||
|
||||
// mark day as modified, close dialog
|
||||
editing_day.addClass('modified');
|
||||
$('#save-changes').button('enable');
|
||||
$('#undo-changes').button('enable');
|
||||
$('.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;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -176,13 +178,15 @@
|
|||
$(this).parents('.shift:first').remove();
|
||||
});
|
||||
|
||||
$('#save-changes').click(function() {
|
||||
$('.save-changes').click(function() {
|
||||
$(this).button('disable').button('option', 'label', "Saving Changes...");
|
||||
okay_to_leave = true;
|
||||
$('#schedule-form').submit();
|
||||
});
|
||||
|
||||
$('#undo-changes').click(function() {
|
||||
$('.undo-changes').click(function() {
|
||||
$(this).button('disable').button('option', 'label', "Refreshing...");
|
||||
okay_to_leave = true;
|
||||
location.href = '${url('schedule.edit')}';
|
||||
});
|
||||
|
||||
|
@ -232,14 +236,20 @@
|
|||
% endfor
|
||||
</%def>
|
||||
|
||||
${h.form(url('schedule.edit'), id="schedule-form")}
|
||||
${self.timesheet()}
|
||||
${h.end_form()}
|
||||
<%def name="edit_tools()">
|
||||
<div class="buttons">
|
||||
<button type="button" class="save-changes" disabled="disabled">Save Changes</button>
|
||||
<button type="button" class="undo-changes" disabled="disabled">Undo Changes</button>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<div class="buttons">
|
||||
<button type="button" id="save-changes" disabled="disabled">Save Changes</button>
|
||||
<button type="button" id="undo-changes" disabled="disabled">Undo Changes</button>
|
||||
</div>
|
||||
<%def name="edit_form()">
|
||||
${h.form(url('schedule.edit'), id='schedule-form')}
|
||||
</%def>
|
||||
|
||||
${self.timesheet(edit_form=edit_form, edit_tools=edit_tools)}
|
||||
|
||||
${edit_tools()}
|
||||
|
||||
<div id="day-editor" style="display: none;">
|
||||
<div class="shifts"></div>
|
||||
|
|
|
@ -48,6 +48,11 @@ class ScheduleView(TimeSheetView):
|
|||
"""
|
||||
View for editing (full) schedule.
|
||||
"""
|
||||
# first process filters; will redirect if any were received
|
||||
form = Form(self.request, schema=ShiftFilter)
|
||||
self.process_filter_form(form)
|
||||
|
||||
# okay then, maybe process saved shift data
|
||||
if self.request.method == 'POST':
|
||||
|
||||
# organize form data by uuid / field
|
||||
|
@ -61,47 +66,42 @@ class ScheduleView(TimeSheetView):
|
|||
data[field][uuid] = self.request.POST[key]
|
||||
break
|
||||
|
||||
# if no fields, don't apply changes (filter form uses POST also)
|
||||
if any(data.itervalues()):
|
||||
# apply delete operations
|
||||
deleted = []
|
||||
for uuid, value in data['delete'].iteritems():
|
||||
assert value == 'delete'
|
||||
shift = Session.query(model.ScheduledShift).get(uuid)
|
||||
assert shift
|
||||
Session.delete(shift)
|
||||
deleted.append(uuid)
|
||||
|
||||
# apply delete operations
|
||||
deleted = []
|
||||
for uuid, value in data['delete'].iteritems():
|
||||
assert value == 'delete'
|
||||
# apply create / update operations
|
||||
created = {}
|
||||
updated = {}
|
||||
time_format = '%a %d %b %Y %I:%M %p'
|
||||
for uuid, employee_uuid in data['start_time'].iteritems():
|
||||
if uuid in deleted:
|
||||
continue
|
||||
if uuid.startswith('new-'):
|
||||
shift = model.ScheduledShift()
|
||||
shift.employee_uuid = data['employee_uuid'][uuid]
|
||||
shift.store_uuid = data['store_uuid'][uuid]
|
||||
Session.add(shift)
|
||||
created[uuid] = shift
|
||||
else:
|
||||
shift = Session.query(model.ScheduledShift).get(uuid)
|
||||
assert shift
|
||||
Session.delete(shift)
|
||||
deleted.append(uuid)
|
||||
updated[uuid] = shift
|
||||
start_time = datetime.datetime.strptime(data['start_time'][uuid], time_format)
|
||||
shift.start_time = make_utc(localtime(self.rattail_config, start_time))
|
||||
end_time = datetime.datetime.strptime(data['end_time'][uuid], time_format)
|
||||
shift.end_time = make_utc(localtime(self.rattail_config, end_time))
|
||||
|
||||
# apply create / update operations
|
||||
created = {}
|
||||
updated = {}
|
||||
time_format = '%a %d %b %Y %I:%M %p'
|
||||
for uuid, employee_uuid in data['start_time'].iteritems():
|
||||
if uuid in deleted:
|
||||
continue
|
||||
if uuid.startswith('new-'):
|
||||
shift = model.ScheduledShift()
|
||||
shift.employee_uuid = data['employee_uuid'][uuid]
|
||||
shift.store_uuid = data['store_uuid'][uuid]
|
||||
Session.add(shift)
|
||||
created[uuid] = shift
|
||||
else:
|
||||
shift = Session.query(model.ScheduledShift).get(uuid)
|
||||
assert shift
|
||||
updated[uuid] = shift
|
||||
start_time = datetime.datetime.strptime(data['start_time'][uuid], time_format)
|
||||
shift.start_time = make_utc(localtime(self.rattail_config, start_time))
|
||||
end_time = datetime.datetime.strptime(data['end_time'][uuid], time_format)
|
||||
shift.end_time = make_utc(localtime(self.rattail_config, end_time))
|
||||
self.request.session.flash("Changes were applied: created {}, updated {}, "
|
||||
"deleted {} Scheduled Shifts".format(
|
||||
len(created), len(updated), len(deleted)))
|
||||
return self.redirect(self.request.route_url('schedule.edit'))
|
||||
|
||||
self.request.session.flash("Changes were applied: created {}, updated {}, "
|
||||
"deleted {} Scheduled Shifts".format(
|
||||
len(created), len(updated), len(deleted)))
|
||||
return self.redirect(self.request.route_url('schedule.edit'))
|
||||
|
||||
form = Form(self.request, schema=ShiftFilter)
|
||||
self.process_filter_form(form)
|
||||
context = self.get_timesheet_context()
|
||||
context['form'] = form
|
||||
context['page_title'] = "Edit Schedule"
|
||||
|
|
Loading…
Reference in a new issue