initial rattail v0.4 port (savepoint)

This commit is contained in:
Lance Edgar 2012-12-14 09:26:15 -08:00
parent 4cd598f33e
commit 79e6a46b94
97 changed files with 6729 additions and 294 deletions

View file

@ -0,0 +1,74 @@
<%def name="global_title()">Rattail</%def>
<%def name="title()"></%def>
<%def name="head_tags()"></%def>
<%def name="home_link()"><h1 class="right">${h.link_to("Home", url('home'))}</h1></%def>
<%def name="menu()"></%def>
<%def name="footer()">
powered by ${h.link_to('Rattail', 'http://rattail.edbob.org', target='_blank')} v${rattail.__version__}
</%def>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html style="direction: ltr;" xmlns="http://www.w3.org/1999/xhtml" lang="en-us">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>${self.global_title()}${' : ' + capture(self.title) if capture(self.title) else ''}</title>
${h.javascript_link(request.static_url('rattail.pyramid:static/js/jquery.js'))}
${h.javascript_link(request.static_url('rattail.pyramid:static/js/jquery.ui.js'))}
${h.javascript_link(request.static_url('rattail.pyramid:static/js/jquery.loading.js'))}
${h.javascript_link(request.static_url('rattail.pyramid:static/js/jquery.autocomplete.js'))}
${h.javascript_link(request.static_url('rattail.pyramid:static/js/rattail.js'))}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/base.css'))}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/layout.css'))}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/grids.css'))}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/filters.css'))}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/forms.css'))}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/autocomplete.css'))}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/smoothness/jquery-ui-1.8.2.custom.css'))}
${self.head_tags()}
</head>
<body>
<div id="container">
<div id="header">
${self.home_link()}
<h1 class="left">${self.title()}</h1>
<div id="login" class="right">
% if request.user:
${h.link_to(request.user.display_name, url('change_password'), class_='username')}
(${h.link_to("logout", url('logout'))})
% else:
${h.link_to("login", url('login'))}
% endif
</div>
</div><!-- header -->
<div id="body">
% if request.session.peek_flash('error'):
<div id="error-messages">
% for error in request.session.pop_flash('error'):
<div class="error">${error}</div>
% endfor
</div>
% endif
% if request.session.peek_flash():
<div id="flash-messages">
% for msg in request.session.pop_flash():
<div class="flash-message">${msg|n}</div>
% endfor
</div>
% endif
${self.body()}
</div><!-- body -->
</div><!-- container -->
<div id="footer">
${self.footer()}
</div>
</body>
</html>

View file

@ -0,0 +1,18 @@
<%inherit file="/form.mako" />
<%def name="title()">${"New "+form.pretty_name if form.creating else form.pretty_name+' : '+h.literal(str(form.fieldset.model))}</%def>
<%def name="head_tags()">
${parent.head_tags()}
<script type="text/javascript">
$(function() {
$('a.delete').click(function() {
if (! confirm("Do you really wish to delete this object?")) {
return false;
}
});
});
</script>
</%def>
${parent.body()}

View file

@ -0,0 +1,13 @@
<%inherit file="/base.mako" />
<%def name="context_menu_items()"></%def>
<div class="form-wrapper">
<ul class="context-menu">
${self.context_menu_items()}
</ul>
${form.render()|n}
</div>

View file

@ -0,0 +1,3 @@
<%namespace file="/autocomplete.mako" import="autocomplete" />
${autocomplete(field_name, service_url, field_value, field_display, width=width, callback=callback)}

View file

@ -0,0 +1,39 @@
<% _focus_rendered = False %>
% for error in fieldset.errors.get(None, []):
<div class="fieldset-error">${error}</div>
% endfor
% for field in fieldset.render_fields.itervalues():
% if field.requires_label:
<div class="field-wrapper ${field.name}">
% for error in field.errors:
<div class="field-error">${error}</div>
% endfor
${field.label_tag()|n}
<div class="field">
${field.render()|n}
</div>
% if 'instructions' in field.metadata:
<span class="instructions">${field.metadata['instructions']}</span>
% endif
</div>
% if not _focus_rendered and (fieldset.focus == field or fieldset.focus is True):
% if not field.is_readonly() and getattr(field.renderer, 'needs_focus', True):
<script language="javascript" type="text/javascript">
$(function() {
% if hasattr(field.renderer, 'focus_name'):
$('#${field.renderer.focus_name}').focus();
% else:
$('#${field.renderer.name}').focus();
% endif
});
</script>
<% _focus_rendered = True %>
% endif
% endif
% endif
% endfor

View file

@ -0,0 +1,12 @@
<div class="fieldset">
% for field in fieldset.render_fields.itervalues():
% if field.requires_label:
<div class="field-wrapper ${field.name}">
${field.label_tag()|n}
<div class="field">
${field.render_readonly()}
</div>
</div>
% endif
% endfor
</div>

View file

@ -0,0 +1,37 @@
<div class="filterset">
${search.begin()}
${search.hidden('filters', True)}
<% visible = [] %>
% for f in search.sorted_filters():
<% f = search.filters[f] %>
<div class="filter" id="filter-${f.name}"${' style="display: none;"' if not search.config.get('include_filter_'+f.name) else ''|n}>
${search.checkbox('include_filter_'+f.name)}
<label for="${f.name}">${f.label}</label>
${f.types_select()}
${f.value_control()}
</div>
% if search.config.get('include_filter_'+f.name):
<% visible.append(f.name) %>
% endif
% endfor
<div class="buttons">
${search.add_filter(visible)}
${search.submit('submit', "Search", style='display: none;' if not visible else None)}
<button type="reset"${' style="display: none;"' if not visible else ''}>Reset</button>
</div>
${search.end()}
% if visible:
<script language="javascript" type="text/javascript">
var filters_to_disable = [
% for field in visible:
'${field}',
% endfor
];
% if not dialog:
$(function() {
disable_filter_options();
});
% endif
</script>
% endif
</div>

View file

@ -0,0 +1,15 @@
<div class="form">
${h.form(form.action_url, enctype='multipart/form-data')}
${form.fieldset.render()|n}
<div class="buttons">
${h.submit('create', form.create_label if form.creating else form.update_label)}
% if form.creating and form.allow_successive_creates:
${h.submit('create_and_continue', form.successive_create_label)}
% endif
<button type="button" onclick="location.href = '${form.cancel_url}';">Cancel</button>
</div>
${h.end_form()}
</div>

View file

@ -0,0 +1,3 @@
<div class="form">
${form.fieldset.render()|n}
</div>

View file

@ -0,0 +1,54 @@
<div class="grid${' '+class_ if class_ else ''}" ${grid.url_attrs()|n}>
<table>
<thead>
<tr>
% if checkboxes:
<th class="checkbox">${h.checkbox('check-all')}</th>
% endif
% for field in grid.iter_fields():
${grid.column_header(field)}
% endfor
% for col in grid.extra_columns:
<th>${col.label}</td>
% endfor
% if grid.deletable:
<th>&nbsp;</th>
% endif
</tr>
</thead>
<tbody>
% for i, row in enumerate(grid.rows):
<% grid._set_active(row) %>
<tr ${grid.row_attrs(i)|n}>
% if checkboxes:
<td class="checkbox">${h.checkbox('check-'+grid.model.uuid, disabled=True)}</td>
% endif
% for field in grid.iter_fields():
<td class="${grid.field_name(field)}">${grid.render_field(field, True)|n}</td>
% endfor
% for col in grid.extra_columns:
<td class="${col.name}">${col.callback(row)|n}</td>
% endfor
% if grid.deletable:
<td class="delete">&nbsp;</td>
% endif
</tr>
% endfor
</tbody>
</table>
% if hasattr(grid, 'pager') and grid.pager:
<div class="pager">
<p class="showing">
showing
${grid.pager.first_item} thru ${grid.pager.last_item} of ${grid.pager.item_count}
</p>
<p class="page-links">
${h.select('grid-page-count', grid.pager.items_per_page, (5, 10, 20, 50, 100))}
per page:&nbsp;
${grid.pager.pager('~3~', onclick='return grid_navigate_page($(this));')}
</p>
</div>
% endif
</div>

View file

@ -0,0 +1,37 @@
<%inherit file="/base.mako" />
<%def name="context_menu_items()"></%def>
<%def name="form()">
% if search:
${search.render()}
% else:
&nbsp;
% endif
</%def>
<%def name="tools()"></%def>
<div class="grid-wrapper">
<table class="grid-header">
<tr>
<td rowspan="2" class="form">
${self.form()}
</td>
<td class="context-menu">
<ul>
${self.context_menu_items()}
</ul>
</td>
</tr>
<tr>
<td class="tools">
${self.tools()}
</td>
</tr>
</table><!-- grid-header -->
${grid}
</div><!-- grid-wrapper -->

View file

@ -0,0 +1,57 @@
<div ${grid.div_attrs()}>
<table>
<thead>
<tr>
% if grid.checkboxes:
<th class="checkbox">${h.checkbox('check-all')}</th>
% endif
% for field in grid.iter_fields():
${grid.column_header(field)}
% endfor
% for col in grid.extra_columns:
<th>${col.label}</td>
% endfor
% if grid.editable:
<th>&nbsp;</th>
% endif
% if grid.deletable:
<th>&nbsp;</th>
% endif
</tr>
</thead>
<tbody>
% for i, row in enumerate(grid.iter_rows(), 1):
<tr ${grid.get_row_attrs(row, i)}>
% if grid.checkboxes:
<td class="checkbox">${grid.checkbox(row)}</td>
% endif
% for field in grid.iter_fields():
<td class="${grid.cell_class(field)}">${grid.render_field(field)}</td>
% endfor
% for col in grid.extra_columns:
<td class="noclick ${col.name}">${col.callback(row)}</td>
% endfor
% if grid.editable:
<td class="noclick edit" url="${grid.get_edit_url(row)}">&nbsp;</td>
% endif
% if grid.deletable:
<td class="noclick delete" url="${grid.get_delete_url(row)}">&nbsp;</td>
% endif
</tr>
% endfor
</tbody>
</table>
% if grid.pager:
<div class="pager">
<p class="showing">
showing ${grid.pager.first_item} thru ${grid.pager.last_item} of ${grid.pager.item_count}
(page ${grid.pager.page} of ${grid.pager.page_count})
</p>
<p class="page-links">
${h.select('grid-page-count', grid.pager.items_per_page, grid.page_count_options())}
per page&nbsp;
${grid.page_links()}
</p>
</div>
% endif
</div>

View file

@ -0,0 +1,36 @@
<div class="filters" url="${search.request.current_route_url()}">
${search.begin()}
${search.hidden('filters', 'true')}
<% visible = [] %>
% for f in search.sorted_filters():
<div class="filter" id="filter-${f.name}"${' style="display: none;"' if not search.config.get('include_filter_'+f.name) else ''|n}>
${search.checkbox('include_filter_'+f.name)}
<label for="${f.name}">${f.label}</label>
${f.types_select()}
<div class="value">
${f.value_control()}
</div>
</div>
% if search.config.get('include_filter_'+f.name):
<% visible.append(f.name) %>
% endif
% endfor
<div class="buttons">
${search.add_filter(visible)}
${search.submit('submit', "Search", style='display: none;' if not visible else None)}
<button type="reset"${' style="display: none;"' if not visible else ''|n}>Reset</button>
</div>
${search.end()}
% if visible:
<script language="javascript" type="text/javascript">
filters_to_disable = [
% for field in visible:
'${field}',
% endfor
];
$(function() {
disable_filter_options();
});
</script>
% endif
</div>

View file

@ -0,0 +1,80 @@
<%inherit file="/base.mako" />
<%def name="title()">Login</%def>
<%def name="head_tags()">
${parent.head_tags()}
${h.stylesheet_link(request.static_url('rattail.pyramid:static/css/login.css'))}
${self.logo_styles()}
</%def>
<%def name="logo_styles()">
<style type="text/css">
#login-logo {
background-image: url(${request.static_url('rattail.pyramid:static/img/logo.jpg')});
background-size: 350px auto;
height: 114.25px;
margin: 25px auto;
width: 350px;
}
</style>
</%def>
<div id="login-logo"></div>
<div class="form">
${h.form('')}
## <input type="hidden" name="login" value="True" />
<input type="hidden" name="referrer" value="${referrer}" />
% if error:
<div class="error">${error}</div>
% endif
<div class="field-wrapper">
<label for="username">Username:</label>
<input type="text" name="username" id="username" value="" />
</div>
<div class="field-wrapper">
<label for="password">Password:</label>
<input type="password" name="password" id="password" value="" />
</div>
<div class="buttons">
${h.submit('submit', "Login")}
<input type="reset" value="Reset" />
</div>
${h.end_form()}
</div>
<script language="javascript" type="text/javascript">
$(function() {
$('form').submit(function() {
if (! $('#username').val()) {
with ($('#username').get(0)) {
select();
focus();
}
return false;
}
if (! $('#password').val()) {
with ($('#password').get(0)) {
select();
focus();
}
return false;
}
return true;
});
$('#username').focus();
});
</script>