Collapse all master4 views back to just 'master'
This commit is contained in:
parent
7c62b6f7a7
commit
2219315ccc
|
@ -28,9 +28,6 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
from .core import View
|
||||
from .master import MasterView
|
||||
from .master2 import MasterView2
|
||||
from .master3 import MasterView3
|
||||
from .master4 import MasterView4
|
||||
|
||||
# TODO: deprecate / remove some of this
|
||||
from .autocomplete import AutocompleteView
|
||||
|
|
|
@ -27,6 +27,3 @@ Views for batches
|
|||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
from .core import BatchMasterView, FileBatchMasterView
|
||||
from .core2 import BatchMasterView2, FileBatchMasterView2
|
||||
from .core3 import BatchMasterView3, FileBatchMasterView3
|
||||
from .core4 import BatchMasterView4, FileBatchMasterView4
|
||||
|
|
|
@ -73,6 +73,33 @@ class BatchMasterView(MasterView):
|
|||
mobile_rows_viewable = True
|
||||
has_worksheet = False
|
||||
|
||||
grid_columns = [
|
||||
'id',
|
||||
'description',
|
||||
'created',
|
||||
'created_by',
|
||||
'rowcount',
|
||||
# 'status_code',
|
||||
# 'complete',
|
||||
'executed',
|
||||
'executed_by',
|
||||
]
|
||||
|
||||
form_fields = [
|
||||
'id',
|
||||
'created',
|
||||
'created_by',
|
||||
'rowcount',
|
||||
'status_code',
|
||||
'executed',
|
||||
'executed_by',
|
||||
'purge',
|
||||
]
|
||||
|
||||
row_labels = {
|
||||
'status_code': "Status",
|
||||
}
|
||||
|
||||
def __init__(self, request):
|
||||
super(BatchMasterView, self).__init__(request)
|
||||
self.handler = self.get_handler()
|
||||
|
@ -114,6 +141,44 @@ class BatchMasterView(MasterView):
|
|||
def allow_worksheet(self, batch):
|
||||
return not batch.executed and not batch.complete
|
||||
|
||||
def configure_grid(self, g):
|
||||
super(BatchMasterView, self).configure_grid(g)
|
||||
|
||||
g.joiners['created_by'] = lambda q: q.join(model.User, model.User.uuid == self.model_class.created_by_uuid)
|
||||
g.joiners['executed_by'] = lambda q: q.outerjoin(model.User, model.User.uuid == self.model_class.executed_by_uuid)
|
||||
|
||||
g.filters['executed'].default_active = True
|
||||
g.filters['executed'].default_verb = 'is_null'
|
||||
|
||||
# TODO: not sure this todo is still relevant?
|
||||
# TODO: in some cases grid has no sorters yet..e.g. when building query for bulk-delete
|
||||
# if hasattr(g, 'sorters'):
|
||||
g.sorters['created_by'] = g.make_sorter(model.User.username)
|
||||
g.sorters['executed_by'] = g.make_sorter(model.User.username)
|
||||
|
||||
g.set_sort_defaults('id', 'desc')
|
||||
|
||||
g.set_enum('status_code', self.model_class.STATUS)
|
||||
|
||||
g.set_type('created', 'datetime')
|
||||
g.set_type('executed', 'datetime')
|
||||
|
||||
g.set_renderer('id', self.render_batch_id)
|
||||
|
||||
g.set_link('id')
|
||||
g.set_link('description')
|
||||
g.set_link('created')
|
||||
g.set_link('executed')
|
||||
|
||||
g.set_label('id', "Batch ID")
|
||||
g.set_label('created_by', "Created by")
|
||||
g.set_label('rowcount', "Rows")
|
||||
g.set_label('status_code', "Status")
|
||||
g.set_label('executed_by', "Executed by")
|
||||
|
||||
def render_batch_id(self, batch, column):
|
||||
return batch.id_str
|
||||
|
||||
def template_kwargs_index(self, **kwargs):
|
||||
kwargs['execute_enabled'] = self.instance_executable(None)
|
||||
if kwargs['execute_enabled'] and self.has_execution_options():
|
||||
|
@ -151,6 +216,82 @@ class BatchMasterView(MasterView):
|
|||
filters['status'] = MobileBatchStatusFilter(self.model_class, 'status', default_value='pending')
|
||||
return filters
|
||||
|
||||
def configure_form(self, f):
|
||||
super(BatchMasterView, self).configure_form(f)
|
||||
|
||||
# id
|
||||
f.set_readonly('id')
|
||||
f.set_renderer('id', self.render_batch_id)
|
||||
f.set_label('id', "Batch ID")
|
||||
|
||||
# created
|
||||
f.set_readonly('created')
|
||||
f.set_readonly('created_by')
|
||||
f.set_renderer('created_by', self.render_user)
|
||||
f.set_label('created_by', "Created by")
|
||||
|
||||
# cognized
|
||||
f.set_renderer('cognized_by', self.render_user)
|
||||
f.set_label('cognized_by', "Cognized by")
|
||||
|
||||
# row count
|
||||
f.set_readonly('rowcount')
|
||||
f.set_label('rowcount', "Row Count")
|
||||
|
||||
# status_code
|
||||
f.set_readonly('status_code')
|
||||
f.set_renderer('status_code', self.make_status_renderer(self.model_class.STATUS))
|
||||
f.set_label('status_code', "Status")
|
||||
|
||||
# executed
|
||||
f.set_readonly('executed')
|
||||
f.set_readonly('executed_by')
|
||||
f.set_renderer('executed_by', self.render_user)
|
||||
f.set_label('executed_by', "Executed by")
|
||||
|
||||
# notes
|
||||
f.set_type('notes', 'text')
|
||||
|
||||
# if self.creating and self.request.user:
|
||||
# batch = fs.model
|
||||
# batch.created_by_uuid = self.request.user.uuid
|
||||
|
||||
if self.creating:
|
||||
f.remove_fields('id',
|
||||
'rowcount',
|
||||
'created',
|
||||
'created_by',
|
||||
'cognized',
|
||||
'cognized_by',
|
||||
'executed',
|
||||
'executed_by',
|
||||
'purge')
|
||||
|
||||
else: # not creating
|
||||
batch = self.get_instance()
|
||||
if not batch.executed:
|
||||
f.remove_fields('executed',
|
||||
'executed_by')
|
||||
|
||||
def make_status_renderer(self, enum):
|
||||
def render_status(batch, field):
|
||||
value = batch.status_code
|
||||
if value is None:
|
||||
return ""
|
||||
status_code_text = enum.get(value, six.text_type(value))
|
||||
if batch.status_text:
|
||||
return HTML.tag('span', title=batch.status_text, c=status_code_text)
|
||||
return status_code_text
|
||||
return render_status
|
||||
|
||||
def render_user(self, batch, field):
|
||||
user = getattr(batch, field)
|
||||
if not user:
|
||||
return ""
|
||||
title = six.text_type(user)
|
||||
url = self.request.route_url('users.view', uuid=user.uuid)
|
||||
return tags.link_to(title, url)
|
||||
|
||||
def _preconfigure_fieldset(self, fs):
|
||||
"""
|
||||
Apply some commonly-useful pre-configuration to the main batch
|
||||
|
@ -240,67 +381,93 @@ class BatchMasterView(MasterView):
|
|||
download_url=download_url)
|
||||
fs.append(fa.Field(name, **kwargs))
|
||||
|
||||
def configure_mobile_form(self, f):
|
||||
super(BatchMasterView, self).configure_mobile_form(f)
|
||||
batch = f.model_instance
|
||||
|
||||
if self.creating:
|
||||
f.remove_fields('id',
|
||||
'rowcount',
|
||||
'created',
|
||||
'created_by',
|
||||
'cognized',
|
||||
'cognized_by',
|
||||
'executed',
|
||||
'executed_by',
|
||||
'purge')
|
||||
|
||||
else: # not creating
|
||||
if not batch.executed:
|
||||
f.remove_fields('executed',
|
||||
'executed_by')
|
||||
if not batch.complete:
|
||||
f.remove_field('complete')
|
||||
|
||||
def save_create_form(self, form):
|
||||
self.before_create(form)
|
||||
|
||||
with Session.no_autoflush:
|
||||
session = self.Session()
|
||||
with session.no_autoflush:
|
||||
|
||||
# transfer form data to batch instance
|
||||
form.fieldset.sync()
|
||||
batch = form.fieldset.model
|
||||
batch = self.objectify(form, self.form_deserialized)
|
||||
|
||||
# current user is batch creator
|
||||
batch.created_by = self.request.user or self.late_login_user()
|
||||
|
||||
# destroy initial batch and re-make using handler
|
||||
# obtain kwargs for making batch via handler, below
|
||||
kwargs = self.get_batch_kwargs(batch)
|
||||
Session.expunge(batch)
|
||||
batch = self.handler.make_batch(Session(), **kwargs)
|
||||
|
||||
Session.flush()
|
||||
# TODO: this needs work yet surely...
|
||||
if 'filename' in form.schema:
|
||||
filedict = kwargs.pop('filename', None)
|
||||
filepath = None
|
||||
if filedict:
|
||||
kwargs['filename'] = '' # null not allowed
|
||||
tempdir = tempfile.mkdtemp()
|
||||
filepath = os.path.join(tempdir, filedict['filename'])
|
||||
tmpinfo = form.deform_form['filename'].widget.tmpstore.get(filedict['uid'])
|
||||
tmpdata = tmpinfo['fp'].read()
|
||||
with open(filepath, 'wb') as f:
|
||||
f.write(tmpdata)
|
||||
|
||||
# TODO: is this still necessary with colander?
|
||||
# destroy initial batch and re-make using handler
|
||||
# if batch in self.Session:
|
||||
# self.Session.expunge(batch)
|
||||
batch = self.handler.make_batch(session, **kwargs)
|
||||
|
||||
self.Session.flush()
|
||||
|
||||
# TODO: this needs work yet surely...
|
||||
# if batch has input data file, let handler properly establish that
|
||||
filename = getattr(batch, 'filename', None)
|
||||
if filename:
|
||||
path = os.path.join(self.upload_dir, filename)
|
||||
if os.path.exists(path):
|
||||
self.handler.set_input_file(batch, path)
|
||||
os.remove(path)
|
||||
if 'filename' in form.schema:
|
||||
if filedict:
|
||||
self.handler.set_input_file(batch, filepath)
|
||||
os.remove(filepath)
|
||||
os.rmdir(tempdir)
|
||||
|
||||
# return this object to replace the original
|
||||
return batch
|
||||
|
||||
# TODO: this is a totaly copy of save_create_form()
|
||||
def save_mobile_create_form(self, form):
|
||||
self.before_create(form)
|
||||
|
||||
with Session.no_autoflush:
|
||||
session = self.Session()
|
||||
with session.no_autoflush:
|
||||
|
||||
# transfer form data to batch instance
|
||||
form.fieldset.sync()
|
||||
batch = form.fieldset.model
|
||||
batch = self.objectify(form, self.form_deserialized)
|
||||
|
||||
# current user is batch creator
|
||||
batch.created_by = self.request.user or self.late_login_user()
|
||||
batch.created_by = self.request.user
|
||||
|
||||
# TODO: is this still necessary with colander?
|
||||
# destroy initial batch and re-make using handler
|
||||
kwargs = self.get_batch_kwargs(batch)
|
||||
Session.expunge(batch)
|
||||
batch = self.handler.make_batch(Session(), **kwargs)
|
||||
if batch in session:
|
||||
session.expunge(batch)
|
||||
batch = self.handler.make_batch(session, **kwargs)
|
||||
|
||||
Session.flush()
|
||||
|
||||
# TODO: this needs work yet surely...
|
||||
# if batch has input data file, let handler properly establish that
|
||||
filename = getattr(batch, 'filename', None)
|
||||
if filename:
|
||||
path = os.path.join(self.upload_dir, filename)
|
||||
if os.path.exists(path):
|
||||
self.handler.set_input_file(batch, path)
|
||||
os.remove(path)
|
||||
|
||||
# return this object to replace the original
|
||||
session.flush()
|
||||
return batch
|
||||
|
||||
def get_batch_kwargs(self, batch, mobile=False):
|
||||
|
@ -367,6 +534,35 @@ class BatchMasterView(MasterView):
|
|||
"""
|
||||
return not batch.executed
|
||||
|
||||
def configure_row_grid(self, g):
|
||||
super(BatchMasterView, self).configure_row_grid(g)
|
||||
|
||||
if 'status_code' in g.filters:
|
||||
g.filters['status_code'].set_value_renderer(grids.filters.EnumValueRenderer(self.model_row_class.STATUS))
|
||||
|
||||
g.set_sort_defaults('sequence')
|
||||
|
||||
if self.model_row_class:
|
||||
g.set_enum('status_code', self.model_row_class.STATUS)
|
||||
|
||||
g.set_renderer('status_code', self.render_row_status)
|
||||
|
||||
g.set_label('sequence', "Seq.")
|
||||
g.set_label('status_code', "Status")
|
||||
g.set_label('item_id', "Item ID")
|
||||
|
||||
def get_row_status_enum(self):
|
||||
return self.model_row_class.STATUS
|
||||
|
||||
def render_row_status(self, row, column):
|
||||
code = row.status_code
|
||||
if code is None:
|
||||
return ""
|
||||
text = self.get_row_status_enum().get(code, six.text_type(code))
|
||||
if row.status_text:
|
||||
return HTML.tag('span', title=row.status_text, c=text)
|
||||
return text
|
||||
|
||||
def create_row(self):
|
||||
"""
|
||||
Only allow creating a new row if the batch hasn't yet been executed.
|
||||
|
@ -387,14 +583,42 @@ class BatchMasterView(MasterView):
|
|||
return self.redirect(self.get_action_url('view', batch, mobile=True))
|
||||
return super(BatchMasterView, self).mobile_create_row()
|
||||
|
||||
def before_create_row(self, form):
|
||||
def save_create_row_form(self, form):
|
||||
batch = self.get_instance()
|
||||
row = form.fieldset.model
|
||||
row = self.objectify(form, self.form_deserialized)
|
||||
self.handler.add_row(batch, row)
|
||||
self.Session.flush()
|
||||
return row
|
||||
|
||||
def after_create_row(self, row):
|
||||
self.handler.refresh_row(row)
|
||||
|
||||
def configure_row_form(self, f):
|
||||
super(BatchMasterView, self).configure_row_form(f)
|
||||
|
||||
# sequence
|
||||
f.set_readonly('sequence')
|
||||
|
||||
# status_code
|
||||
if self.model_row_class:
|
||||
f.set_enum('status_code', self.model_row_class.STATUS)
|
||||
f.set_renderer('status_code', self.render_row_status)
|
||||
f.set_readonly('status_code')
|
||||
f.set_label('status_code', "Status")
|
||||
|
||||
def configure_mobile_row_form(self, f):
|
||||
super(BatchMasterView, self).configure_mobile_row_form(f)
|
||||
|
||||
# sequence
|
||||
f.set_readonly('sequence')
|
||||
|
||||
# status_code
|
||||
if self.model_row_class:
|
||||
f.set_enum('status_code', self.model_row_class.STATUS)
|
||||
f.set_renderer('status_code', self.render_row_status)
|
||||
f.set_readonly('status_code')
|
||||
f.set_label('status_code', "Status")
|
||||
|
||||
def make_default_row_grid_tools(self, batch):
|
||||
if self.rows_creatable and not batch.executed:
|
||||
permission_prefix = self.get_permission_prefix()
|
||||
|
@ -1007,6 +1231,26 @@ class FileBatchMasterView(BatchMasterView):
|
|||
os.makedirs(uploads)
|
||||
return uploads
|
||||
|
||||
def configure_form(self, f):
|
||||
super(FileBatchMasterView, self).configure_form(f)
|
||||
|
||||
# filename
|
||||
f.set_renderer('filename', self.render_filename)
|
||||
f.set_label('filename', "Data File")
|
||||
if self.editing:
|
||||
f.set_readonly('filename')
|
||||
|
||||
if self.creating:
|
||||
if 'filename' not in f.fields:
|
||||
f.fields.insert(0, 'filename')
|
||||
tmpstore = SessionFileUploadTempStore(self.request)
|
||||
f.set_node('filename', colander.SchemaNode(deform.FileData(), widget=dfwidget.FileUploadWidget(tmpstore)))
|
||||
|
||||
def render_filename(self, batch, field):
|
||||
path = batch.filepath(self.rattail_config, filename=batch.filename)
|
||||
url = self.get_action_url('download', batch)
|
||||
return self.render_file_field(path, url)
|
||||
|
||||
def _preconfigure_fieldset(self, fs):
|
||||
super(FileBatchMasterView, self)._preconfigure_fieldset(fs)
|
||||
fs.filename.set(label="Data File", renderer=FileFieldRenderer.new(self))
|
||||
|
|
|
@ -1,129 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2017 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Base views for maintaining batches
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import six
|
||||
|
||||
from rattail.db import model
|
||||
|
||||
from webhelpers2.html import HTML
|
||||
|
||||
from tailbone import grids
|
||||
from tailbone.views import MasterView2
|
||||
from tailbone.views.batch import BatchMasterView, FileBatchMasterView
|
||||
from tailbone.views.batch.core import MobileBatchStatusFilter
|
||||
|
||||
|
||||
class BatchMasterView2(MasterView2, BatchMasterView):
|
||||
"""
|
||||
Base class for all "batch master" views
|
||||
"""
|
||||
|
||||
grid_columns = [
|
||||
'id',
|
||||
'description',
|
||||
'created',
|
||||
'created_by',
|
||||
'rowcount',
|
||||
# 'status_code',
|
||||
# 'complete',
|
||||
'executed',
|
||||
'executed_by',
|
||||
]
|
||||
|
||||
def configure_grid(self, g):
|
||||
super(BatchMasterView2, self).configure_grid(g)
|
||||
|
||||
g.joiners['created_by'] = lambda q: q.join(model.User, model.User.uuid == self.model_class.created_by_uuid)
|
||||
g.joiners['executed_by'] = lambda q: q.outerjoin(model.User, model.User.uuid == self.model_class.executed_by_uuid)
|
||||
|
||||
g.filters['executed'].default_active = True
|
||||
g.filters['executed'].default_verb = 'is_null'
|
||||
|
||||
# TODO: not sure this todo is still relevant?
|
||||
# TODO: in some cases grid has no sorters yet..e.g. when building query for bulk-delete
|
||||
# if hasattr(g, 'sorters'):
|
||||
g.sorters['created_by'] = g.make_sorter(model.User.username)
|
||||
g.sorters['executed_by'] = g.make_sorter(model.User.username)
|
||||
|
||||
g.set_sort_defaults('id', 'desc')
|
||||
|
||||
g.set_enum('status_code', self.model_class.STATUS)
|
||||
|
||||
g.set_type('created', 'datetime')
|
||||
g.set_type('executed', 'datetime')
|
||||
|
||||
g.set_renderer('id', self.render_batch_id)
|
||||
|
||||
g.set_link('id')
|
||||
g.set_link('description')
|
||||
g.set_link('created')
|
||||
g.set_link('executed')
|
||||
|
||||
g.set_label('id', "Batch ID")
|
||||
g.set_label('created_by', "Created by")
|
||||
g.set_label('rowcount', "Rows")
|
||||
g.set_label('status_code', "Status")
|
||||
g.set_label('executed_by', "Executed by")
|
||||
|
||||
def render_batch_id(self, batch, column):
|
||||
return batch.id_str
|
||||
|
||||
def configure_row_grid(self, g):
|
||||
super(BatchMasterView2, self).configure_row_grid(g)
|
||||
|
||||
if 'status_code' in g.filters:
|
||||
g.filters['status_code'].set_value_renderer(grids.filters.EnumValueRenderer(self.model_row_class.STATUS))
|
||||
|
||||
g.set_sort_defaults('sequence')
|
||||
|
||||
if self.model_row_class:
|
||||
g.set_enum('status_code', self.model_row_class.STATUS)
|
||||
|
||||
g.set_renderer('status_code', self.render_row_status)
|
||||
|
||||
g.set_label('sequence', "Seq.")
|
||||
g.set_label('status_code', "Status")
|
||||
g.set_label('item_id', "Item ID")
|
||||
|
||||
def get_row_status_enum(self):
|
||||
return self.model_row_class.STATUS
|
||||
|
||||
def render_row_status(self, row, column):
|
||||
code = row.status_code
|
||||
if code is None:
|
||||
return ""
|
||||
text = self.get_row_status_enum().get(code, six.text_type(code))
|
||||
if row.status_text:
|
||||
return HTML.tag('span', title=row.status_text, c=text)
|
||||
return text
|
||||
|
||||
|
||||
class FileBatchMasterView2(BatchMasterView2, FileBatchMasterView):
|
||||
"""
|
||||
Base class for all file-based "batch master" views
|
||||
"""
|
|
@ -1,205 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2018 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Base views for maintaining batches
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import six
|
||||
import colander
|
||||
import deform
|
||||
from deform import widget as dfwidget
|
||||
from pyramid_deform import SessionFileUploadTempStore
|
||||
from webhelpers2.html import tags
|
||||
|
||||
from tailbone.views import MasterView3
|
||||
from tailbone.views.batch import BatchMasterView2, FileBatchMasterView2
|
||||
|
||||
|
||||
class BatchMasterView3(MasterView3, BatchMasterView2):
|
||||
"""
|
||||
Base class for all "batch master" views
|
||||
"""
|
||||
|
||||
form_fields = [
|
||||
'id',
|
||||
'created',
|
||||
'created_by',
|
||||
'rowcount',
|
||||
'status_code',
|
||||
'executed',
|
||||
'executed_by',
|
||||
'purge',
|
||||
]
|
||||
|
||||
def configure_form(self, f):
|
||||
super(BatchMasterView3, self).configure_form(f)
|
||||
|
||||
# id
|
||||
f.set_readonly('id')
|
||||
f.set_renderer('id', self.render_batch_id)
|
||||
f.set_label('id', "Batch ID")
|
||||
|
||||
# created
|
||||
f.set_readonly('created')
|
||||
f.set_readonly('created_by')
|
||||
f.set_renderer('created_by', self.render_user)
|
||||
f.set_label('created_by', "Created by")
|
||||
|
||||
# cognized
|
||||
f.set_renderer('cognized_by', self.render_user)
|
||||
f.set_label('cognized_by', "Cognized by")
|
||||
|
||||
# row count
|
||||
f.set_readonly('rowcount')
|
||||
f.set_label('rowcount', "Row Count")
|
||||
|
||||
# status_code
|
||||
f.set_readonly('status_code')
|
||||
f.set_renderer('status_code', self.make_status_renderer(self.model_class.STATUS))
|
||||
f.set_label('status_code', "Status")
|
||||
|
||||
# executed
|
||||
f.set_readonly('executed')
|
||||
f.set_readonly('executed_by')
|
||||
f.set_renderer('executed_by', self.render_user)
|
||||
f.set_label('executed_by', "Executed by")
|
||||
|
||||
# notes
|
||||
f.set_type('notes', 'text')
|
||||
|
||||
# if self.creating and self.request.user:
|
||||
# batch = fs.model
|
||||
# batch.created_by_uuid = self.request.user.uuid
|
||||
|
||||
if self.creating:
|
||||
f.remove_fields('id',
|
||||
'rowcount',
|
||||
'created',
|
||||
'created_by',
|
||||
'cognized',
|
||||
'cognized_by',
|
||||
'executed',
|
||||
'executed_by',
|
||||
'purge')
|
||||
|
||||
else: # not creating
|
||||
batch = self.get_instance()
|
||||
if not batch.executed:
|
||||
f.remove_fields('executed',
|
||||
'executed_by')
|
||||
|
||||
def save_create_form(self, form):
|
||||
self.before_create(form)
|
||||
|
||||
session = self.Session()
|
||||
with session.no_autoflush:
|
||||
|
||||
# transfer form data to batch instance
|
||||
batch = self.objectify(form, self.form_deserialized)
|
||||
|
||||
# current user is batch creator
|
||||
batch.created_by = self.request.user or self.late_login_user()
|
||||
|
||||
# obtain kwargs for making batch via handler, below
|
||||
kwargs = self.get_batch_kwargs(batch)
|
||||
|
||||
# TODO: this needs work yet surely...
|
||||
if 'filename' in form.schema:
|
||||
filedict = kwargs.pop('filename', None)
|
||||
filepath = None
|
||||
if filedict:
|
||||
kwargs['filename'] = '' # null not allowed
|
||||
tempdir = tempfile.mkdtemp()
|
||||
filepath = os.path.join(tempdir, filedict['filename'])
|
||||
tmpinfo = form.deform_form['filename'].widget.tmpstore.get(filedict['uid'])
|
||||
tmpdata = tmpinfo['fp'].read()
|
||||
with open(filepath, 'wb') as f:
|
||||
f.write(tmpdata)
|
||||
|
||||
# TODO: is this still necessary with colander?
|
||||
# destroy initial batch and re-make using handler
|
||||
# if batch in self.Session:
|
||||
# self.Session.expunge(batch)
|
||||
batch = self.handler.make_batch(session, **kwargs)
|
||||
|
||||
self.Session.flush()
|
||||
|
||||
# TODO: this needs work yet surely...
|
||||
# if batch has input data file, let handler properly establish that
|
||||
if 'filename' in form.schema:
|
||||
if filedict:
|
||||
self.handler.set_input_file(batch, filepath)
|
||||
os.remove(filepath)
|
||||
os.rmdir(tempdir)
|
||||
|
||||
return batch
|
||||
|
||||
def make_status_renderer(self, enum):
|
||||
def render_status(batch, field):
|
||||
value = batch.status_code
|
||||
if value is None:
|
||||
return ""
|
||||
status_code_text = enum.get(value, six.text_type(value))
|
||||
if batch.status_text:
|
||||
return HTML.tag('span', title=batch.status_text, c=status_code_text)
|
||||
return status_code_text
|
||||
return render_status
|
||||
|
||||
def render_user(self, batch, field):
|
||||
user = getattr(batch, field)
|
||||
if not user:
|
||||
return ""
|
||||
title = six.text_type(user)
|
||||
url = self.request.route_url('users.view', uuid=user.uuid)
|
||||
return tags.link_to(title, url)
|
||||
|
||||
|
||||
class FileBatchMasterView3(BatchMasterView3, FileBatchMasterView2):
|
||||
"""
|
||||
Base class for all file-based "batch master" views
|
||||
"""
|
||||
|
||||
def configure_form(self, f):
|
||||
super(FileBatchMasterView3, self).configure_form(f)
|
||||
|
||||
# filename
|
||||
f.set_renderer('filename', self.render_filename)
|
||||
f.set_label('filename', "Data File")
|
||||
if self.editing:
|
||||
f.set_readonly('filename')
|
||||
|
||||
if self.creating:
|
||||
if 'filename' not in f.fields:
|
||||
f.fields.insert(0, 'filename')
|
||||
tmpstore = SessionFileUploadTempStore(self.request)
|
||||
f.set_node('filename', colander.SchemaNode(deform.FileData(), widget=dfwidget.FileUploadWidget(tmpstore)))
|
||||
|
||||
def render_filename(self, batch, field):
|
||||
path = batch.filepath(self.rattail_config, filename=batch.filename)
|
||||
url = self.get_action_url('download', batch)
|
||||
return self.render_file_field(path, url)
|
|
@ -1,127 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2018 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Base views for maintaining batches
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
from tailbone.views import MasterView4
|
||||
from tailbone.views.batch import BatchMasterView3, FileBatchMasterView3
|
||||
|
||||
|
||||
class BatchMasterView4(MasterView4, BatchMasterView3):
|
||||
"""
|
||||
Base class for all "batch master" views
|
||||
"""
|
||||
|
||||
row_labels = {
|
||||
'status_code': "Status",
|
||||
}
|
||||
|
||||
def configure_mobile_form(self, f):
|
||||
super(BatchMasterView4, self).configure_mobile_form(f)
|
||||
batch = f.model_instance
|
||||
|
||||
if self.creating:
|
||||
f.remove_fields('id',
|
||||
'rowcount',
|
||||
'created',
|
||||
'created_by',
|
||||
'cognized',
|
||||
'cognized_by',
|
||||
'executed',
|
||||
'executed_by',
|
||||
'purge')
|
||||
|
||||
else: # not creating
|
||||
if not batch.executed:
|
||||
f.remove_fields('executed',
|
||||
'executed_by')
|
||||
if not batch.complete:
|
||||
f.remove_field('complete')
|
||||
|
||||
def save_mobile_create_form(self, form):
|
||||
self.before_create(form)
|
||||
session = self.Session()
|
||||
with session.no_autoflush:
|
||||
|
||||
# transfer form data to batch instance
|
||||
batch = self.objectify(form, self.form_deserialized)
|
||||
|
||||
# current user is batch creator
|
||||
batch.created_by = self.request.user
|
||||
|
||||
# TODO: is this still necessary with colander?
|
||||
# destroy initial batch and re-make using handler
|
||||
kwargs = self.get_batch_kwargs(batch)
|
||||
if batch in session:
|
||||
session.expunge(batch)
|
||||
batch = self.handler.make_batch(session, **kwargs)
|
||||
|
||||
session.flush()
|
||||
return batch
|
||||
|
||||
def configure_row_form(self, f):
|
||||
super(BatchMasterView4, self).configure_row_form(f)
|
||||
|
||||
# sequence
|
||||
f.set_readonly('sequence')
|
||||
|
||||
# status_code
|
||||
if self.model_row_class:
|
||||
f.set_enum('status_code', self.model_row_class.STATUS)
|
||||
f.set_renderer('status_code', self.render_row_status)
|
||||
f.set_readonly('status_code')
|
||||
f.set_label('status_code', "Status")
|
||||
|
||||
def configure_mobile_row_form(self, f):
|
||||
super(BatchMasterView4, self).configure_mobile_row_form(f)
|
||||
|
||||
# sequence
|
||||
f.set_readonly('sequence')
|
||||
|
||||
# status_code
|
||||
if self.model_row_class:
|
||||
f.set_enum('status_code', self.model_row_class.STATUS)
|
||||
f.set_renderer('status_code', self.render_row_status)
|
||||
f.set_readonly('status_code')
|
||||
f.set_label('status_code', "Status")
|
||||
|
||||
# NOTE: must override default logic here, by doing nothing
|
||||
def before_create_row(self, form):
|
||||
pass
|
||||
|
||||
def save_create_row_form(self, form):
|
||||
batch = self.get_instance()
|
||||
row = self.objectify(form, self.form_deserialized)
|
||||
self.handler.add_row(batch, row)
|
||||
self.Session.flush()
|
||||
return row
|
||||
|
||||
|
||||
class FileBatchMasterView4(BatchMasterView4, FileBatchMasterView3):
|
||||
"""
|
||||
Base class for all file-based "batch master" views
|
||||
"""
|
||||
|
|
@ -30,7 +30,7 @@ import sqlalchemy as sa
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views.batch import BatchMasterView4 as BatchMasterView
|
||||
from tailbone.views.batch import BatchMasterView
|
||||
|
||||
|
||||
class ImporterBatchView(BatchMasterView):
|
||||
|
|
|
@ -30,7 +30,7 @@ from rattail.db import model
|
|||
|
||||
from webhelpers2.html import tags
|
||||
|
||||
from tailbone.views.batch import BatchMasterView4 as BatchMasterView
|
||||
from tailbone.views.batch import BatchMasterView
|
||||
|
||||
|
||||
class PricingBatchView(BatchMasterView):
|
||||
|
|
|
@ -37,7 +37,7 @@ from pyramid.response import FileResponse
|
|||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone import grids
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class EmailBouncesView(MasterView):
|
||||
|
|
|
@ -28,7 +28,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||
from tailbone.views import MasterView, AutocompleteView
|
||||
|
||||
|
||||
class BrandsView(MasterView):
|
||||
|
|
|
@ -28,7 +28,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class CategoriesView(MasterView):
|
||||
|
|
|
@ -29,7 +29,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
from rattail.db import model
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class CustomerGroupsView(MasterView):
|
||||
|
|
|
@ -39,7 +39,7 @@ from webhelpers2.html import HTML, tags
|
|||
|
||||
from tailbone import grids
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||
from tailbone.views import MasterView, AutocompleteView
|
||||
|
||||
from rattail.db import model
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ from sqlalchemy import orm
|
|||
from rattail.db import model
|
||||
from rattail.time import localtime
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.util import raw_datetime
|
||||
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ from rattail.db import model
|
|||
from webhelpers2.html import tags
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class CustomerOrdersView(MasterView):
|
||||
|
|
|
@ -31,7 +31,7 @@ import logging
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
|
@ -33,7 +33,7 @@ from rattail.db import model
|
|||
from deform import widget as dfwidget
|
||||
|
||||
from tailbone import grids
|
||||
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||
from tailbone.views import MasterView, AutocompleteView
|
||||
|
||||
|
||||
class DepartmentsView(MasterView):
|
||||
|
|
|
@ -28,7 +28,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class DepositLinksView(MasterView):
|
||||
|
|
|
@ -37,7 +37,7 @@ from deform import widget as dfwidget
|
|||
from webhelpers2.html import HTML
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import View, MasterView4 as MasterView
|
||||
from tailbone.views import View, MasterView
|
||||
|
||||
|
||||
class ProfilesView(MasterView):
|
||||
|
|
|
@ -37,7 +37,7 @@ from webhelpers2.html import tags, HTML
|
|||
|
||||
from tailbone import grids
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||
from tailbone.views import MasterView, AutocompleteView
|
||||
|
||||
|
||||
class EmployeesView(MasterView):
|
||||
|
|
|
@ -36,7 +36,7 @@ from pyramid.response import FileResponse
|
|||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone import forms2 as forms
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class ExportMasterView(MasterView):
|
||||
|
|
|
@ -28,7 +28,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class FamiliesView(MasterView):
|
||||
|
|
|
@ -35,7 +35,7 @@ import formencode as fe
|
|||
from webhelpers2.html import tags
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views.batch import FileBatchMasterView4 as FileBatchMasterView
|
||||
from tailbone.views.batch import FileBatchMasterView
|
||||
|
||||
|
||||
ACTION_OPTIONS = OrderedDict([
|
||||
|
|
|
@ -43,8 +43,8 @@ from deform import widget as dfwidget
|
|||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone import forms, forms2, grids
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views.batch import BatchMasterView4 as BatchMasterView
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.views.batch import BatchMasterView
|
||||
|
||||
|
||||
class InventoryAdjustmentReasonsView(MasterView):
|
||||
|
|
|
@ -30,7 +30,7 @@ from rattail.db import model
|
|||
|
||||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone.views.batch import BatchMasterView4 as BatchMasterView
|
||||
from tailbone.views.batch import BatchMasterView
|
||||
|
||||
|
||||
class LabelBatchView(BatchMasterView):
|
||||
|
|
|
@ -31,7 +31,7 @@ from rattail.db import model
|
|||
from pyramid.httpexceptions import HTTPFound
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class ProfilesView(MasterView):
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,422 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2017 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Master View
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import sqlalchemy_continuum as continuum
|
||||
|
||||
from tailbone import grids
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class MasterView2(MasterView):
|
||||
"""
|
||||
Base "master" view class. All model master views should derive from this.
|
||||
"""
|
||||
sortable = True
|
||||
rows_pageable = True
|
||||
mobile_pageable = True
|
||||
labels = {'uuid': "UUID"}
|
||||
|
||||
@classmethod
|
||||
def get_grid_factory(cls):
|
||||
"""
|
||||
Returns the grid factory or class which is to be used when creating new
|
||||
grid instances.
|
||||
"""
|
||||
return getattr(cls, 'grid_factory', grids.Grid)
|
||||
|
||||
@classmethod
|
||||
def get_row_grid_factory(cls):
|
||||
"""
|
||||
Returns the grid factory or class which is to be used when creating new
|
||||
row grid instances.
|
||||
"""
|
||||
return getattr(cls, 'row_grid_factory', grids.Grid)
|
||||
|
||||
@classmethod
|
||||
def get_version_grid_factory(cls):
|
||||
"""
|
||||
Returns the grid factory or class which is to be used when creating new
|
||||
version grid instances.
|
||||
"""
|
||||
return getattr(cls, 'version_grid_factory', grids.Grid)
|
||||
|
||||
@classmethod
|
||||
def get_mobile_grid_factory(cls):
|
||||
"""
|
||||
Must return a callable to be used when creating new mobile grid
|
||||
instances. Instead of overriding this, you can set
|
||||
:attr:`mobile_grid_factory`. Default factory is :class:`MobileGrid`.
|
||||
"""
|
||||
return getattr(cls, 'mobile_grid_factory', grids.MobileGrid)
|
||||
|
||||
@classmethod
|
||||
def get_mobile_row_grid_factory(cls):
|
||||
"""
|
||||
Must return a callable to be used when creating new mobile row grid
|
||||
instances. Instead of overriding this, you can set
|
||||
:attr:`mobile_row_grid_factory`. Default factory is :class:`MobileGrid`.
|
||||
"""
|
||||
return getattr(cls, 'mobile_row_grid_factory', grids.MobileGrid)
|
||||
|
||||
def get_effective_data(self, session=None, **kwargs):
|
||||
"""
|
||||
Convenience method which returns the "effective" data for the master
|
||||
grid, filtered and sorted to match what would show on the UI, but not
|
||||
paged etc.
|
||||
"""
|
||||
if session is None:
|
||||
session = self.Session()
|
||||
kwargs.setdefault('pageable', False)
|
||||
grid = self.make_grid(session=session, **kwargs)
|
||||
return grid.make_visible_data()
|
||||
|
||||
def make_grid(self, factory=None, key=None, data=None, columns=None, **kwargs):
|
||||
"""
|
||||
Creates a new grid instance
|
||||
"""
|
||||
if factory is None:
|
||||
factory = self.get_grid_factory()
|
||||
if key is None:
|
||||
key = self.get_grid_key()
|
||||
if data is None:
|
||||
data = self.get_data(session=kwargs.get('session'))
|
||||
if columns is None:
|
||||
columns = self.get_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
kwargs = self.make_grid_kwargs(**kwargs)
|
||||
grid = factory(key, data, columns, **kwargs)
|
||||
self.configure_grid(grid)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
||||
def make_row_grid(self, factory=None, key=None, data=None, columns=None, **kwargs):
|
||||
"""
|
||||
Make and return a new (configured) rows grid instance.
|
||||
"""
|
||||
instance = kwargs.pop('instance', None)
|
||||
if not instance:
|
||||
instance = self.get_instance()
|
||||
|
||||
if factory is None:
|
||||
factory = self.get_row_grid_factory()
|
||||
if key is None:
|
||||
key = self.get_row_grid_key()
|
||||
if data is None:
|
||||
data = self.get_row_data(instance)
|
||||
if columns is None:
|
||||
columns = self.get_row_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
kwargs = self.make_row_grid_kwargs(**kwargs)
|
||||
|
||||
grid = factory(key, data, columns, **kwargs)
|
||||
self.configure_row_grid(grid)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
||||
def make_version_grid(self, factory=None, key=None, data=None, columns=None, **kwargs):
|
||||
"""
|
||||
Creates a new version grid instance
|
||||
"""
|
||||
instance = kwargs.pop('instance', None)
|
||||
if not instance:
|
||||
instance = self.get_instance()
|
||||
|
||||
if factory is None:
|
||||
factory = self.get_version_grid_factory()
|
||||
if key is None:
|
||||
key = self.get_version_grid_key()
|
||||
if data is None:
|
||||
data = self.get_version_data(instance)
|
||||
if columns is None:
|
||||
columns = self.get_version_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
kwargs = self.make_version_grid_kwargs(**kwargs)
|
||||
grid = factory(key, data, columns, **kwargs)
|
||||
self.configure_version_grid(grid)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
||||
def make_mobile_grid(self, factory=None, key=None, data=None, columns=None, **kwargs):
|
||||
"""
|
||||
Creates a new mobile grid instance
|
||||
"""
|
||||
if factory is None:
|
||||
factory = self.get_mobile_grid_factory()
|
||||
if key is None:
|
||||
key = self.get_mobile_grid_key()
|
||||
if data is None:
|
||||
data = self.get_mobile_data(session=kwargs.get('session'))
|
||||
if columns is None:
|
||||
columns = self.get_mobile_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
kwargs.setdefault('mobile', True)
|
||||
kwargs = self.make_mobile_grid_kwargs(**kwargs)
|
||||
grid = factory(key, data, columns, **kwargs)
|
||||
self.configure_mobile_grid(grid)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
||||
def make_mobile_row_grid(self, factory=None, key=None, data=None, columns=None, **kwargs):
|
||||
"""
|
||||
Make a new (configured) rows grid instance for mobile.
|
||||
"""
|
||||
instance = kwargs.pop('instance', self.get_instance())
|
||||
|
||||
if factory is None:
|
||||
factory = self.get_mobile_row_grid_factory()
|
||||
if key is None:
|
||||
key = 'mobile.{}.{}'.format(self.get_grid_key(), self.request.matchdict[self.get_model_key()])
|
||||
if data is None:
|
||||
data = self.get_mobile_row_data(instance)
|
||||
if columns is None:
|
||||
columns = self.get_mobile_row_grid_columns()
|
||||
|
||||
kwargs.setdefault('request', self.request)
|
||||
kwargs.setdefault('mobile', True)
|
||||
kwargs = self.make_mobile_row_grid_kwargs(**kwargs)
|
||||
grid = factory(key, data, columns, **kwargs)
|
||||
self.configure_mobile_row_grid(grid)
|
||||
grid.load_settings()
|
||||
return grid
|
||||
|
||||
def get_grid_columns(self):
|
||||
if hasattr(self, 'grid_columns'):
|
||||
return self.grid_columns
|
||||
# TODO
|
||||
raise NotImplementedError
|
||||
|
||||
def get_row_grid_columns(self):
|
||||
if hasattr(self, 'row_grid_columns'):
|
||||
return self.row_grid_columns
|
||||
# TODO
|
||||
raise NotImplementedError
|
||||
|
||||
def get_version_grid_columns(self):
|
||||
if hasattr(self, 'version_grid_columns'):
|
||||
return self.version_grid_columns
|
||||
# TODO
|
||||
return [
|
||||
'issued_at',
|
||||
'user',
|
||||
'remote_addr',
|
||||
'comment',
|
||||
]
|
||||
|
||||
def get_mobile_grid_columns(self):
|
||||
if hasattr(self, 'mobile_grid_columns'):
|
||||
return self.mobile_grid_columns
|
||||
# TODO
|
||||
return ['listitem']
|
||||
|
||||
def get_mobile_row_grid_columns(self):
|
||||
if hasattr(self, 'mobile_row_grid_columns'):
|
||||
return self.mobile_row_grid_columns
|
||||
# TODO
|
||||
return ['listitem']
|
||||
|
||||
def make_grid_kwargs(self, **kwargs):
|
||||
"""
|
||||
Return a dictionary of kwargs to be passed to the factory when creating
|
||||
new grid instances.
|
||||
"""
|
||||
defaults = {
|
||||
'model_class': getattr(self, 'model_class', None),
|
||||
'width': 'full',
|
||||
'filterable': self.filterable,
|
||||
'sortable': self.sortable,
|
||||
'pageable': self.pageable,
|
||||
'extra_row_class': self.grid_extra_class,
|
||||
'url': lambda obj: self.get_action_url('view', obj),
|
||||
'checkboxes': self.checkboxes or (
|
||||
self.mergeable and self.request.has_perm('{}.merge'.format(self.get_permission_prefix()))),
|
||||
'checked': self.checked,
|
||||
}
|
||||
if 'main_actions' not in kwargs and 'more_actions' not in kwargs:
|
||||
main, more = self.get_grid_actions()
|
||||
defaults['main_actions'] = main
|
||||
defaults['more_actions'] = more
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def make_row_grid_kwargs(self, **kwargs):
|
||||
"""
|
||||
Return a dict of kwargs to be used when constructing a new rows grid.
|
||||
"""
|
||||
permission_prefix = self.get_permission_prefix()
|
||||
|
||||
defaults = {
|
||||
'model_class': self.model_row_class,
|
||||
'width': 'full',
|
||||
'filterable': self.rows_filterable,
|
||||
'sortable': self.rows_sortable,
|
||||
'pageable': self.rows_pageable,
|
||||
'default_pagesize': self.rows_default_pagesize,
|
||||
'extra_row_class': self.row_grid_extra_class,
|
||||
'url': lambda obj: self.get_row_action_url('view', obj),
|
||||
}
|
||||
|
||||
if self.has_rows and 'main_actions' not in defaults:
|
||||
actions = []
|
||||
|
||||
# view action
|
||||
if self.rows_viewable:
|
||||
view = lambda r, i: self.get_row_action_url('view', r)
|
||||
actions.append(grids.GridAction('view', icon='zoomin', url=view))
|
||||
|
||||
# edit action
|
||||
if self.rows_editable:
|
||||
actions.append(grids.GridAction('edit', icon='pencil', url=self.row_edit_action_url))
|
||||
|
||||
# delete action
|
||||
if self.rows_deletable and self.request.has_perm('{}.delete_row'.format(permission_prefix)):
|
||||
actions.append(grids.GridAction('delete', icon='trash', url=self.row_delete_action_url))
|
||||
defaults['delete_speedbump'] = self.rows_deletable_speedbump
|
||||
|
||||
defaults['main_actions'] = actions
|
||||
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def make_version_grid_kwargs(self, **kwargs):
|
||||
"""
|
||||
Return a dictionary of kwargs to be passed to the factory when
|
||||
constructing a new version grid.
|
||||
"""
|
||||
defaults = {
|
||||
'model_class': continuum.transaction_class(self.get_model_class()),
|
||||
'width': 'full',
|
||||
'pageable': True,
|
||||
}
|
||||
if 'main_actions' not in kwargs:
|
||||
route = '{}.version'.format(self.get_route_prefix())
|
||||
instance = kwargs.get('instance') or self.get_instance()
|
||||
url = lambda txn, i: self.request.route_url(route, uuid=instance.uuid, txnid=txn.id)
|
||||
defaults['main_actions'] = [
|
||||
self.make_action('view', icon='zoomin', url=url),
|
||||
]
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def make_mobile_grid_kwargs(self, **kwargs):
|
||||
"""
|
||||
Must return a dictionary of kwargs to be passed to the factory when
|
||||
creating new mobile grid instances.
|
||||
"""
|
||||
defaults = {
|
||||
'model_class': getattr(self, 'model_class', None),
|
||||
'pageable': self.mobile_pageable,
|
||||
'sortable': False,
|
||||
'filterable': self.mobile_filterable,
|
||||
'renderers': self.make_mobile_grid_renderers(),
|
||||
'url': lambda obj: self.get_action_url('view', obj, mobile=True),
|
||||
}
|
||||
# TODO: this seems wrong..
|
||||
if self.mobile_filterable:
|
||||
defaults['filters'] = self.make_mobile_filters()
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def make_mobile_row_grid_kwargs(self, **kwargs):
|
||||
"""
|
||||
Must return a dictionary of kwargs to be passed to the factory when
|
||||
creating new mobile *row* grid instances.
|
||||
"""
|
||||
defaults = {
|
||||
'model_class': self.model_row_class,
|
||||
# TODO
|
||||
'pageable': self.pageable,
|
||||
'sortable': False,
|
||||
'filterable': self.mobile_rows_filterable,
|
||||
'renderers': self.make_mobile_row_grid_renderers(),
|
||||
'url': lambda obj: self.get_row_action_url('view', obj, mobile=True),
|
||||
}
|
||||
# TODO: this seems wrong..
|
||||
if self.mobile_rows_filterable:
|
||||
defaults['filters'] = self.make_mobile_row_filters()
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def make_mobile_grid_renderers(self):
|
||||
return {
|
||||
'listitem': self.render_mobile_listitem,
|
||||
}
|
||||
|
||||
def render_mobile_listitem(self, obj, i):
|
||||
return obj
|
||||
|
||||
def make_mobile_row_grid_renderers(self):
|
||||
return {
|
||||
'listitem': self.render_mobile_row_listitem,
|
||||
}
|
||||
|
||||
def render_mobile_row_listitem(self, obj, i):
|
||||
return obj
|
||||
|
||||
def grid_extra_class(self, obj, i):
|
||||
"""
|
||||
Returns string of extra class(es) for the table row corresponding to
|
||||
the given object, or ``None``.
|
||||
"""
|
||||
|
||||
def row_grid_extra_class(self, obj, i):
|
||||
"""
|
||||
Returns string of extra class(es) for the table row corresponding to
|
||||
the given row object, or ``None``.
|
||||
"""
|
||||
|
||||
def set_labels(self, obj):
|
||||
for key, label in self.labels.items():
|
||||
obj.set_label(key, label)
|
||||
|
||||
def configure_grid(self, grid):
|
||||
self.set_labels(grid)
|
||||
|
||||
def configure_row_grid(self, grid):
|
||||
pass
|
||||
|
||||
def configure_version_grid(self, g):
|
||||
g.set_sort_defaults('issued_at', 'desc')
|
||||
g.set_renderer('comment', self.render_version_comment)
|
||||
g.set_label('issued_at', "Changed")
|
||||
g.set_label('user', "Changed by")
|
||||
g.set_label('remote_addr', "IP Address")
|
||||
# TODO: why does this render '#' as url?
|
||||
# g.set_link('issued_at')
|
||||
|
||||
def render_version_comment(self, transaction, column):
|
||||
return transaction.meta.get('comment', "")
|
||||
|
||||
def configure_mobile_grid(self, grid):
|
||||
pass
|
||||
|
||||
def configure_mobile_row_grid(self, grid):
|
||||
pass
|
|
@ -1,178 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2017 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Master View
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import os
|
||||
|
||||
from sqlalchemy import orm
|
||||
|
||||
import deform
|
||||
from webhelpers2.html import tags
|
||||
|
||||
from tailbone import forms2 as forms
|
||||
from tailbone.views import MasterView2
|
||||
|
||||
|
||||
class MasterView3(MasterView2):
|
||||
"""
|
||||
Base "master" view class. All model master views should derive from this.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def get_form_factory(cls):
|
||||
"""
|
||||
Returns the grid factory or class which is to be used when creating new
|
||||
grid instances.
|
||||
"""
|
||||
return getattr(cls, 'form_factory', forms.Form)
|
||||
|
||||
def make_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs):
|
||||
"""
|
||||
Creates a new form for the given model class/instance
|
||||
"""
|
||||
if factory is None:
|
||||
factory = self.get_form_factory()
|
||||
if fields is None:
|
||||
fields = self.get_form_fields()
|
||||
if schema is None:
|
||||
schema = self.make_form_schema()
|
||||
|
||||
# TODO: SQLAlchemy class instance is assumed *unless* we get a dict
|
||||
# (seems like we should be smarter about this somehow)
|
||||
# if not self.creating and not isinstance(instance, dict):
|
||||
if not self.creating:
|
||||
kwargs['model_instance'] = instance
|
||||
kwargs = self.make_form_kwargs(**kwargs)
|
||||
form = factory(fields, schema, **kwargs)
|
||||
self.configure_form(form)
|
||||
return form
|
||||
|
||||
def make_form_schema(self):
|
||||
if not self.model_class:
|
||||
# TODO
|
||||
raise NotImplementedError
|
||||
|
||||
def get_form_fields(self):
|
||||
if hasattr(self, 'form_fields'):
|
||||
return self.form_fields
|
||||
# TODO
|
||||
# raise NotImplementedError
|
||||
|
||||
def make_form_kwargs(self, **kwargs):
|
||||
"""
|
||||
Return a dictionary of kwargs to be passed to the factory when creating
|
||||
new form instances.
|
||||
"""
|
||||
defaults = {
|
||||
'request': self.request,
|
||||
'readonly': self.viewing,
|
||||
'model_class': getattr(self, 'model_class', None),
|
||||
'action_url': self.request.current_route_url(_query=None),
|
||||
}
|
||||
if self.creating:
|
||||
kwargs.setdefault('cancel_url', self.get_index_url())
|
||||
else:
|
||||
instance = kwargs['model_instance']
|
||||
kwargs.setdefault('cancel_url', self.get_action_url('view', instance))
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def configure_form(self, form):
|
||||
"""
|
||||
Configure the primary form. By default this just sets any primary key
|
||||
fields to be readonly (if we have a :attr:`model_class`).
|
||||
"""
|
||||
if self.editing:
|
||||
model_class = self.get_model_class(error=False)
|
||||
if model_class:
|
||||
mapper = orm.class_mapper(model_class)
|
||||
for key in mapper.primary_key:
|
||||
for field in form.fields:
|
||||
if field == key.name:
|
||||
form.set_readonly(field)
|
||||
break
|
||||
|
||||
form.remove_field('uuid')
|
||||
|
||||
self.set_labels(form)
|
||||
|
||||
def render_file_field(self, path, url=None, filename=None):
|
||||
"""
|
||||
Convenience for rendering a file with optional download link
|
||||
"""
|
||||
if not filename:
|
||||
filename = os.path.basename(path)
|
||||
content = "{} ({})".format(filename, self.readable_size(path))
|
||||
if url:
|
||||
return tags.link_to(content, url)
|
||||
return content
|
||||
|
||||
def readable_size(self, path):
|
||||
# TODO: this was shamelessly copied from FormAlchemy ...
|
||||
length = self.get_size(path)
|
||||
if length == 0:
|
||||
return '0 KB'
|
||||
if length <= 1024:
|
||||
return '1 KB'
|
||||
if length > 1048576:
|
||||
return '%0.02f MB' % (length / 1048576.0)
|
||||
return '%0.02f KB' % (length / 1024.0)
|
||||
|
||||
def get_size(self, path):
|
||||
try:
|
||||
return os.path.getsize(path)
|
||||
except os.error:
|
||||
return 0
|
||||
|
||||
def validate_form(self, form):
|
||||
controls = self.request.POST.items()
|
||||
try:
|
||||
self.form_deserialized = form.validate(controls)
|
||||
except deform.ValidationFailure:
|
||||
return False
|
||||
return True
|
||||
|
||||
def objectify(self, form, data):
|
||||
obj = form.schema.objectify(data, context=form.model_instance)
|
||||
return obj
|
||||
|
||||
def save_create_form(self, form):
|
||||
self.before_create(form)
|
||||
with self.Session().no_autoflush:
|
||||
obj = self.objectify(form, self.form_deserialized)
|
||||
self.before_create_flush(obj, form)
|
||||
self.Session.add(obj)
|
||||
self.Session.flush()
|
||||
return obj
|
||||
|
||||
def before_create_flush(self, obj, form):
|
||||
pass
|
||||
|
||||
def save_edit_form(self, form):
|
||||
obj = self.objectify(form, self.form_deserialized)
|
||||
self.after_edit(obj)
|
||||
self.Session.flush()
|
|
@ -1,319 +0,0 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2018 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Master View (v4)
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import deform
|
||||
|
||||
from tailbone import forms2 as forms
|
||||
from tailbone.views import MasterView3
|
||||
|
||||
|
||||
class MasterView4(MasterView3):
|
||||
"""
|
||||
Base "master" view class. All model master views should derive from this.
|
||||
"""
|
||||
row_labels = {}
|
||||
|
||||
def make_mobile_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs):
|
||||
"""
|
||||
Creates a new mobile form for the given model class/instance.
|
||||
"""
|
||||
if factory is None:
|
||||
factory = self.get_mobile_form_factory()
|
||||
if fields is None:
|
||||
fields = self.get_mobile_form_fields()
|
||||
if schema is None:
|
||||
schema = self.make_mobile_form_schema()
|
||||
|
||||
if not self.creating:
|
||||
kwargs['model_instance'] = instance
|
||||
kwargs = self.make_mobile_form_kwargs(**kwargs)
|
||||
form = factory(fields, schema, **kwargs)
|
||||
self.configure_mobile_form(form)
|
||||
return form
|
||||
|
||||
def make_row_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs):
|
||||
"""
|
||||
Creates a new row form for the given model class/instance.
|
||||
"""
|
||||
if factory is None:
|
||||
factory = self.get_row_form_factory()
|
||||
if fields is None:
|
||||
fields = self.get_row_form_fields()
|
||||
if schema is None:
|
||||
schema = self.make_row_form_schema()
|
||||
|
||||
if not self.creating:
|
||||
kwargs['model_instance'] = instance
|
||||
kwargs = self.make_row_form_kwargs(**kwargs)
|
||||
form = factory(fields, schema, **kwargs)
|
||||
self.configure_row_form(form)
|
||||
return form
|
||||
|
||||
def make_mobile_row_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs):
|
||||
"""
|
||||
Creates a new mobile form for the given model class/instance.
|
||||
"""
|
||||
if factory is None:
|
||||
factory = self.get_mobile_row_form_factory()
|
||||
if fields is None:
|
||||
fields = self.get_mobile_row_form_fields()
|
||||
if schema is None:
|
||||
schema = self.make_mobile_row_form_schema()
|
||||
|
||||
if not self.creating:
|
||||
kwargs['model_instance'] = instance
|
||||
kwargs = self.make_mobile_row_form_kwargs(**kwargs)
|
||||
form = factory(fields, schema, **kwargs)
|
||||
self.configure_mobile_row_form(form)
|
||||
return form
|
||||
|
||||
@classmethod
|
||||
def get_mobile_form_factory(cls):
|
||||
"""
|
||||
Returns the factory or class which is to be used when creating new
|
||||
mobile forms.
|
||||
"""
|
||||
return getattr(cls, 'mobile_form_factory', forms.Form)
|
||||
|
||||
@classmethod
|
||||
def get_row_form_factory(cls):
|
||||
"""
|
||||
Returns the factory or class which is to be used when creating new row
|
||||
forms.
|
||||
"""
|
||||
return getattr(cls, 'row_form_factory', forms.Form)
|
||||
|
||||
@classmethod
|
||||
def get_mobile_row_form_factory(cls):
|
||||
"""
|
||||
Returns the factory or class which is to be used when creating new
|
||||
mobile row forms.
|
||||
"""
|
||||
return getattr(cls, 'mobile_row_form_factory', forms.Form)
|
||||
|
||||
def make_mobile_form_schema(self):
|
||||
if not self.model_class:
|
||||
# TODO
|
||||
raise NotImplementedError
|
||||
|
||||
def make_row_form_schema(self):
|
||||
if not self.model_row_class:
|
||||
# TODO
|
||||
raise NotImplementedError
|
||||
|
||||
def make_mobile_row_form_schema(self):
|
||||
if not self.model_row_class:
|
||||
# TODO
|
||||
raise NotImplementedError
|
||||
|
||||
def get_mobile_form_fields(self):
|
||||
if hasattr(self, 'mobile_form_fields'):
|
||||
return self.mobile_form_fields
|
||||
# TODO
|
||||
# raise NotImplementedError
|
||||
|
||||
def get_row_form_fields(self):
|
||||
if hasattr(self, 'row_form_fields'):
|
||||
return self.row_form_fields
|
||||
# TODO
|
||||
# raise NotImplementedError
|
||||
|
||||
def get_mobile_row_form_fields(self):
|
||||
if hasattr(self, 'mobile_row_form_fields'):
|
||||
return self.mobile_row_form_fields
|
||||
# TODO
|
||||
# raise NotImplementedError
|
||||
|
||||
def make_mobile_form_kwargs(self, **kwargs):
|
||||
"""
|
||||
Return a dictionary of kwargs to be passed to the factory when creating
|
||||
new mobile forms.
|
||||
"""
|
||||
defaults = {
|
||||
'request': self.request,
|
||||
'readonly': self.viewing,
|
||||
'model_class': getattr(self, 'model_class', None),
|
||||
'action_url': self.request.current_route_url(_query=None),
|
||||
}
|
||||
if self.creating:
|
||||
defaults['cancel_url'] = self.get_index_url(mobile=True)
|
||||
else:
|
||||
instance = kwargs['model_instance']
|
||||
defaults['cancel_url'] = self.get_action_url('view', instance, mobile=True)
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def make_row_form_kwargs(self, **kwargs):
|
||||
"""
|
||||
Return a dictionary of kwargs to be passed to the factory when creating
|
||||
new row forms.
|
||||
"""
|
||||
defaults = {
|
||||
'request': self.request,
|
||||
'readonly': self.viewing,
|
||||
'model_class': getattr(self, 'model_row_class', None),
|
||||
'action_url': self.request.current_route_url(_query=None),
|
||||
}
|
||||
if self.creating:
|
||||
kwargs.setdefault('cancel_url', self.request.get_referrer())
|
||||
else:
|
||||
instance = kwargs['model_instance']
|
||||
kwargs.setdefault('cancel_url', self.get_row_action_url('view', instance))
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def make_mobile_row_form_kwargs(self, **kwargs):
|
||||
"""
|
||||
Return a dictionary of kwargs to be passed to the factory when creating
|
||||
new mobile row forms.
|
||||
"""
|
||||
defaults = {
|
||||
'request': self.request,
|
||||
'readonly': self.viewing,
|
||||
'model_class': getattr(self, 'model_row_class', None),
|
||||
'action_url': self.request.current_route_url(_query=None),
|
||||
}
|
||||
if self.creating:
|
||||
defaults['cancel_url'] = self.request.get_referrer()
|
||||
else:
|
||||
instance = kwargs['model_instance']
|
||||
defaults['cancel_url'] = self.get_row_action_url('view', instance, mobile=True)
|
||||
defaults.update(kwargs)
|
||||
return defaults
|
||||
|
||||
def configure_mobile_form(self, form):
|
||||
"""
|
||||
Configure the primary mobile form.
|
||||
"""
|
||||
# TODO: is any of this stuff from configure_form() needed?
|
||||
# if self.editing:
|
||||
# model_class = self.get_model_class(error=False)
|
||||
# if model_class:
|
||||
# mapper = orm.class_mapper(model_class)
|
||||
# for key in mapper.primary_key:
|
||||
# for field in form.fields:
|
||||
# if field == key.name:
|
||||
# form.set_readonly(field)
|
||||
# break
|
||||
# form.remove_field('uuid')
|
||||
|
||||
self.set_labels(form)
|
||||
|
||||
def configure_row_grid(self, grid):
|
||||
super(MasterView4, self).configure_row_grid(grid)
|
||||
self.set_row_labels(grid)
|
||||
|
||||
def configure_row_form(self, form):
|
||||
"""
|
||||
Configure a row form.
|
||||
"""
|
||||
# TODO: is any of this stuff from configure_form() needed?
|
||||
# if self.editing:
|
||||
# model_class = self.get_model_class(error=False)
|
||||
# if model_class:
|
||||
# mapper = orm.class_mapper(model_class)
|
||||
# for key in mapper.primary_key:
|
||||
# for field in form.fields:
|
||||
# if field == key.name:
|
||||
# form.set_readonly(field)
|
||||
# break
|
||||
# form.remove_field('uuid')
|
||||
|
||||
self.set_row_labels(form)
|
||||
|
||||
def configure_mobile_row_form(self, form):
|
||||
"""
|
||||
Configure the mobile row form.
|
||||
"""
|
||||
# TODO: is any of this stuff from configure_form() needed?
|
||||
# if self.editing:
|
||||
# model_class = self.get_model_class(error=False)
|
||||
# if model_class:
|
||||
# mapper = orm.class_mapper(model_class)
|
||||
# for key in mapper.primary_key:
|
||||
# for field in form.fields:
|
||||
# if field == key.name:
|
||||
# form.set_readonly(field)
|
||||
# break
|
||||
# form.remove_field('uuid')
|
||||
|
||||
self.set_row_labels(form)
|
||||
|
||||
def set_row_labels(self, obj):
|
||||
for key, label in self.row_labels.items():
|
||||
obj.set_label(key, label)
|
||||
|
||||
def validate_mobile_form(self, form):
|
||||
controls = self.request.POST.items()
|
||||
try:
|
||||
self.form_deserialized = form.validate(controls)
|
||||
except deform.ValidationFailure:
|
||||
return False
|
||||
return True
|
||||
|
||||
def validate_row_form(self, form):
|
||||
controls = self.request.POST.items()
|
||||
try:
|
||||
self.form_deserialized = form.validate(controls)
|
||||
except deform.ValidationFailure:
|
||||
return False
|
||||
return True
|
||||
|
||||
def validate_mobile_row_form(self, form):
|
||||
controls = self.request.POST.items()
|
||||
try:
|
||||
self.form_deserialized = form.validate(controls)
|
||||
except deform.ValidationFailure:
|
||||
return False
|
||||
return True
|
||||
|
||||
def save_mobile_create_form(self, form):
|
||||
self.before_create(form)
|
||||
with self.Session.no_autoflush:
|
||||
obj = self.objectify(form, self.form_deserialized)
|
||||
self.before_create_flush(obj, form)
|
||||
self.Session.add(obj)
|
||||
self.Session.flush()
|
||||
return obj
|
||||
|
||||
# TODO: still need to verify this logic
|
||||
def save_create_row_form(self, form):
|
||||
# self.before_create(form)
|
||||
# with self.Session().no_autoflush:
|
||||
# obj = self.objectify(form, self.form_deserialized)
|
||||
# self.before_create_flush(obj, form)
|
||||
obj = self.objectify(form, self.form_deserialized)
|
||||
self.Session.add(obj)
|
||||
self.Session.flush()
|
||||
return obj
|
||||
|
||||
def save_edit_row_form(self, form):
|
||||
obj = self.objectify(form, self.form_deserialized)
|
||||
self.after_edit_row(obj)
|
||||
self.Session.flush()
|
||||
return obj
|
|
@ -37,7 +37,7 @@ from pyramid import httpexceptions
|
|||
from webhelpers2.html import tags, HTML
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.util import raw_datetime
|
||||
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ from rattail.db import model, api
|
|||
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
|
||||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||
from tailbone.views import MasterView, AutocompleteView
|
||||
|
||||
|
||||
class PeopleView(MasterView):
|
||||
|
|
|
@ -35,7 +35,7 @@ import wtforms
|
|||
from webhelpers2.html import HTML
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class PrincipalMasterView(MasterView):
|
||||
|
|
|
@ -47,7 +47,7 @@ from webhelpers2.html import tags, HTML
|
|||
|
||||
from tailbone import forms2 as forms, grids
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||
from tailbone.views import MasterView, AutocompleteView
|
||||
from tailbone.progress import SessionProgress
|
||||
from tailbone.util import raw_datetime
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ from rattail.db import model
|
|||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class PurchaseView(MasterView):
|
||||
|
|
|
@ -31,7 +31,7 @@ from rattail.db import model
|
|||
from webhelpers2.html import tags
|
||||
|
||||
from tailbone import grids
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class PurchaseCreditView(MasterView):
|
||||
|
|
|
@ -38,7 +38,7 @@ from webhelpers2.html import tags
|
|||
|
||||
# from tailbone import forms
|
||||
from tailbone import forms2
|
||||
from tailbone.views.batch import BatchMasterView4 as BatchMasterView
|
||||
from tailbone.views.batch import BatchMasterView
|
||||
|
||||
|
||||
class PurchasingBatchView(BatchMasterView):
|
||||
|
|
|
@ -28,7 +28,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class ReportCodesView(MasterView):
|
||||
|
|
|
@ -32,7 +32,7 @@ from rattail.db import model
|
|||
|
||||
import colander
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class SettingsView(MasterView):
|
||||
|
|
|
@ -33,7 +33,7 @@ import humanize
|
|||
from rattail.db import model
|
||||
from rattail.time import localtime
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
def render_shift_length(shift, field):
|
||||
|
|
|
@ -32,7 +32,7 @@ from rattail.db import model
|
|||
|
||||
import colander
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class StoresView(MasterView):
|
||||
|
|
|
@ -29,7 +29,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
from rattail.db import model
|
||||
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class SubdepartmentsView(MasterView):
|
||||
|
|
|
@ -26,7 +26,7 @@ Views with info about the underlying Rattail tables
|
|||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class TablesView(MasterView):
|
||||
|
|
|
@ -28,7 +28,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
|
||||
from rattail.db import model
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class TaxesView(MasterView):
|
||||
|
|
|
@ -32,7 +32,7 @@ from tailbone import views
|
|||
from tailbone.db import TempmonSession
|
||||
|
||||
|
||||
class MasterView(views.MasterView4):
|
||||
class MasterView(views.MasterView):
|
||||
"""
|
||||
Base class for tempmon views.
|
||||
"""
|
||||
|
|
|
@ -31,7 +31,7 @@ import six
|
|||
from rattail.time import localtime
|
||||
|
||||
from tailbone.db import TrainwreckSession
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
|
||||
|
||||
class TransactionView(MasterView):
|
||||
|
|
|
@ -43,7 +43,7 @@ from rattail.upgrades import get_upgrade_handler
|
|||
from deform import widget as dfwidget
|
||||
from webhelpers2.html import tags, HTML
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.progress import SessionProgress, get_progress_session
|
||||
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ from webhelpers2.html import HTML, tags
|
|||
|
||||
from tailbone import forms2 as forms
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import MasterView4 as MasterView
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.views.principal import PrincipalMasterView, PermissionsRenderer
|
||||
|
||||
|
||||
|
|
2
tailbone/views/vendors/catalogs.py
vendored
2
tailbone/views/vendors/catalogs.py
vendored
|
@ -39,7 +39,7 @@ from webhelpers2.html import tags
|
|||
|
||||
from tailbone import forms2 as forms
|
||||
from tailbone.db import Session
|
||||
from tailbone.views.batch import FileBatchMasterView4 as FileBatchMasterView
|
||||
from tailbone.views.batch import FileBatchMasterView
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
2
tailbone/views/vendors/core.py
vendored
2
tailbone/views/vendors/core.py
vendored
|
@ -32,7 +32,7 @@ from rattail.db import model
|
|||
|
||||
from webhelpers2.html import tags
|
||||
|
||||
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||
from tailbone.views import MasterView, AutocompleteView
|
||||
|
||||
|
||||
class VendorsView(MasterView):
|
||||
|
|
2
tailbone/views/vendors/invoices.py
vendored
2
tailbone/views/vendors/invoices.py
vendored
|
@ -33,7 +33,7 @@ from rattail.vendors.invoices import iter_invoice_parsers, require_invoice_parse
|
|||
import colander
|
||||
from deform import widget as dfwidget
|
||||
|
||||
from tailbone.views.batch import FileBatchMasterView4 as FileBatchMasterView
|
||||
from tailbone.views.batch import FileBatchMasterView
|
||||
|
||||
|
||||
class VendorInvoicesView(FileBatchMasterView):
|
||||
|
|
Loading…
Reference in a new issue