diff --git a/tailbone/templates/master/view.mako b/tailbone/templates/master/view.mako index 22bdfb00..fcddff05 100644 --- a/tailbone/templates/master/view.mako +++ b/tailbone/templates/master/view.mako @@ -3,6 +3,23 @@ <%def name="title()">${model_title}: ${instance_title} +<%def name="head_tags()"> + ${parent.head_tags()} + % if master.has_rows: + ${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js'))} + + + % endif + + <%def name="context_menu_items()">
  • ${h.link_to("Back to {}".format(model_title_plural), index_url)}
  • ${h.link_to("Permalink for this {}".format(model_title), action_url('view', instance))}
  • @@ -24,3 +41,7 @@
    ${form.render()|n}
    + +% if master.has_rows: + ${rows_grid|n} +% endif diff --git a/tailbone/views/master.py b/tailbone/views/master.py index 562755ed..acf6e9bf 100644 --- a/tailbone/views/master.py +++ b/tailbone/views/master.py @@ -37,7 +37,7 @@ import formalchemy from pyramid import httpexceptions from pyramid.renderers import get_renderer, render_to_response, render -from tailbone import forms +from tailbone import forms, newgrids as grids from tailbone.views import View from tailbone.newgrids import filters, AlchemyGrid, GridAction @@ -67,6 +67,11 @@ class MasterView(View): grid_index = None use_index_links = False + # ROW-RELATED ATTRS FOLLOW: + + has_rows = False + model_row_class = None + @property def Session(self): """ @@ -139,12 +144,105 @@ class MasterView(View): if instance is None: instance = self.get_instance() form = self.make_form(instance) - return self.render_to_response('view', { + if self.has_rows: + + # If user just refreshed the page with a reset instruction, issue a + # redirect in order to clear out the query string. + if self.request.GET.get('reset-to-default-filters') == 'true': + return self.redirect(self.request.current_route_url(_query=None)) + + grid = self.make_row_grid(instance=instance) + if self.request.params.get('partial'): + self.request.response.content_type = b'text/html' + self.request.response.text = grid.render_grid() + return self.request.response + + context = { 'instance': instance, 'instance_title': self.get_instance_title(instance), 'instance_editable': self.editable_instance(instance), 'instance_deletable': self.deletable_instance(instance), - 'form': form}) + 'form': form, + } + if self.has_rows: + context['rows_grid'] = grid.render_complete(allow_save_defaults=False, + tools=self.make_row_grid_tools()) + return self.render_to_response('view', context) + + def make_row_grid_tools(self): + pass + + def make_row_grid(self, **kwargs): + """ + Make and return a new (configured) rows grid instance. + """ + instance = kwargs.pop('instance', self.get_instance()) + data = self.get_row_data(instance) + kwargs = self.make_row_grid_kwargs(**kwargs) + key = '{}.{}'.format(self.get_grid_key(), self.request.matchdict[self.get_model_key()]) + grid = grids.AlchemyGrid(key, self.request, data=data, model_class=self.model_row_class, **kwargs) + self._preconfigure_row_grid(grid) + self.configure_row_grid(grid) + grid.load_settings() + return grid + + def _preconfigure_row_grid(self, g): + pass + + def configure_row_grid(self, grid): + grid.configure() + + def get_row_data(self, instance): + """ + Generate the base data set for a rows grid. + """ + raise NotImplementedError + + @classmethod + def get_row_route_prefix(cls): + """ + Route prefix specific to the row-level views for a batch, e.g. + ``'vendorcatalogs.rows'``. + """ + return "{}.rows".format(cls.get_route_prefix()) + + @classmethod + def get_row_permission_prefix(cls): + """ + Permission prefix specific to the row-level data for this batch type, + e.g. ``'vendorcatalogs.rows'``. + """ + return "{}.rows".format(cls.get_permission_prefix()) + + def make_row_grid_kwargs(self, **kwargs): + """ + Return a dict of kwargs to be used when constructing a new rows grid. + """ + route_prefix = self.get_row_route_prefix() + permission_prefix = self.get_row_permission_prefix() + + defaults = { + 'width': 'full', + 'filterable': True, + 'sortable': True, + 'pageable': True, + 'row_attrs': self.row_grid_row_attrs, + 'model_title': self.get_row_model_title(), + 'model_title_plural': self.get_row_model_title_plural(), + 'permission_prefix': permission_prefix, + 'route_prefix': route_prefix, + } + defaults.update(kwargs) + return defaults + + def row_grid_row_attrs(self, row, i): + return {} + + def get_row_model_title(self): + return "{} Row".format(self.get_model_title()) + + def get_row_model_title_plural(self): + return "{} Rows".format(self.get_model_title()) def view_index(self): """