Remove all deprecated use_buefy
logic
also remove some static files no longer used, etc.
This commit is contained in:
parent
01e5eee981
commit
9faaea881d
|
@ -24,12 +24,9 @@
|
||||||
Forms Core
|
Forms Core
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import six
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
from sqlalchemy.ext.associationproxy import AssociationProxy, ASSOCIATION_PROXY
|
from sqlalchemy.ext.associationproxy import AssociationProxy, ASSOCIATION_PROXY
|
||||||
|
@ -338,7 +335,7 @@ class Form(object):
|
||||||
model_instance=None, model_class=None, appstruct=UNSPECIFIED, nodes={}, enums={}, labels={},
|
model_instance=None, model_class=None, appstruct=UNSPECIFIED, nodes={}, enums={}, labels={},
|
||||||
assume_local_times=False, renderers=None, renderer_kwargs={},
|
assume_local_times=False, renderers=None, renderer_kwargs={},
|
||||||
hidden={}, widgets={}, defaults={}, validators={}, required={}, helptext={}, focus_spec=None,
|
hidden={}, widgets={}, defaults={}, validators={}, required={}, helptext={}, focus_spec=None,
|
||||||
action_url=None, cancel_url=None, use_buefy=True, component='tailbone-form',
|
action_url=None, cancel_url=None, component='tailbone-form',
|
||||||
vuejs_field_converters={},
|
vuejs_field_converters={},
|
||||||
# TODO: ugh this is getting out hand!
|
# TODO: ugh this is getting out hand!
|
||||||
can_edit_help=False, edit_help_url=None, route_prefix=None,
|
can_edit_help=False, edit_help_url=None, route_prefix=None,
|
||||||
|
@ -377,7 +374,6 @@ class Form(object):
|
||||||
self.focus_spec = focus_spec
|
self.focus_spec = focus_spec
|
||||||
self.action_url = action_url
|
self.action_url = action_url
|
||||||
self.cancel_url = cancel_url
|
self.cancel_url = cancel_url
|
||||||
self.use_buefy = use_buefy
|
|
||||||
self.component = component
|
self.component = component
|
||||||
self.vuejs_field_converters = vuejs_field_converters or {}
|
self.vuejs_field_converters = vuejs_field_converters or {}
|
||||||
self.can_edit_help = can_edit_help
|
self.can_edit_help = can_edit_help
|
||||||
|
@ -758,10 +754,7 @@ class Form(object):
|
||||||
|
|
||||||
def render(self, template=None, **kwargs):
|
def render(self, template=None, **kwargs):
|
||||||
if not template:
|
if not template:
|
||||||
if self.readonly and not self.use_buefy:
|
template = '/forms/form.mako'
|
||||||
template = '/forms/form_readonly.mako'
|
|
||||||
else:
|
|
||||||
template = '/forms/form.mako'
|
|
||||||
context = kwargs
|
context = kwargs
|
||||||
context['form'] = self
|
context['form'] = self
|
||||||
return render(template, context)
|
return render(template, context)
|
||||||
|
@ -806,10 +799,7 @@ class Form(object):
|
||||||
|
|
||||||
def render_deform(self, dform=None, template=None, **kwargs):
|
def render_deform(self, dform=None, template=None, **kwargs):
|
||||||
if not template:
|
if not template:
|
||||||
if self.use_buefy:
|
template = '/forms/deform_buefy.mako'
|
||||||
template = '/forms/deform_buefy.mako'
|
|
||||||
else:
|
|
||||||
template = '/forms/deform.mako'
|
|
||||||
|
|
||||||
if dform is None:
|
if dform is None:
|
||||||
dform = self.make_deform_form()
|
dform = self.make_deform_form()
|
||||||
|
@ -829,11 +819,8 @@ class Form(object):
|
||||||
context.setdefault('form_kwargs', {})
|
context.setdefault('form_kwargs', {})
|
||||||
# TODO: deprecate / remove the latter option here
|
# TODO: deprecate / remove the latter option here
|
||||||
if self.auto_disable_save or self.auto_disable:
|
if self.auto_disable_save or self.auto_disable:
|
||||||
if self.use_buefy:
|
context['form_kwargs'].setdefault('ref', self.component_studly)
|
||||||
context['form_kwargs'].setdefault('ref', self.component_studly)
|
context['form_kwargs']['@submit'] = 'submit{}'.format(self.component_studly)
|
||||||
context['form_kwargs']['@submit'] = 'submit{}'.format(self.component_studly)
|
|
||||||
else:
|
|
||||||
context['form_kwargs']['class_'] = 'autodisable'
|
|
||||||
if self.focus_spec:
|
if self.focus_spec:
|
||||||
context['form_kwargs']['data-focus'] = self.focus_spec
|
context['form_kwargs']['data-focus'] = self.focus_spec
|
||||||
context['request'] = self.request
|
context['request'] = self.request
|
||||||
|
@ -975,8 +962,7 @@ class Form(object):
|
||||||
if self.readonly or fieldname in self.readonly_fields:
|
if self.readonly or fieldname in self.readonly_fields:
|
||||||
html = self.render_field_value(fieldname) or HTML.tag('span')
|
html = self.render_field_value(fieldname) or HTML.tag('span')
|
||||||
elif field:
|
elif field:
|
||||||
html = field.serialize(use_buefy=True,
|
html = field.serialize(**self.get_renderer_kwargs(fieldname))
|
||||||
**self.get_renderer_kwargs(fieldname))
|
|
||||||
html = HTML.literal(html)
|
html = HTML.literal(html)
|
||||||
|
|
||||||
# may need a complex label
|
# may need a complex label
|
||||||
|
@ -1064,7 +1050,7 @@ class Form(object):
|
||||||
value = self.obtain_value(record, field_name)
|
value = self.obtain_value(record, field_name)
|
||||||
if value is None:
|
if value is None:
|
||||||
return ""
|
return ""
|
||||||
return six.text_type(value)
|
return str(value)
|
||||||
|
|
||||||
def render_datetime(self, record, field_name):
|
def render_datetime(self, record, field_name):
|
||||||
value = self.obtain_value(record, field_name)
|
value = self.obtain_value(record, field_name)
|
||||||
|
@ -1099,7 +1085,7 @@ class Form(object):
|
||||||
return "(${:0,.2f})".format(0 - value)
|
return "(${:0,.2f})".format(0 - value)
|
||||||
return "${:0,.2f}".format(value)
|
return "${:0,.2f}".format(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return six.text_type(value)
|
return str(value)
|
||||||
|
|
||||||
def render_quantity(self, obj, field):
|
def render_quantity(self, obj, field):
|
||||||
value = self.obtain_value(obj, field)
|
value = self.obtain_value(obj, field)
|
||||||
|
@ -1124,8 +1110,8 @@ class Form(object):
|
||||||
return ""
|
return ""
|
||||||
enum = self.enums.get(field_name)
|
enum = self.enums.get(field_name)
|
||||||
if enum and value in enum:
|
if enum and value in enum:
|
||||||
return six.text_type(enum[value])
|
return str(enum[value])
|
||||||
return six.text_type(value)
|
return str(value)
|
||||||
|
|
||||||
def render_codeblock(self, record, field_name):
|
def render_codeblock(self, record, field_name):
|
||||||
value = self.obtain_value(record, field_name)
|
value = self.obtain_value(record, field_name)
|
||||||
|
@ -1193,8 +1179,8 @@ class Form(object):
|
||||||
controls[i][1] = 'true'
|
controls[i][1] = 'true'
|
||||||
elif value is False:
|
elif value is False:
|
||||||
controls[i][1] = 'false'
|
controls[i][1] = 'false'
|
||||||
elif not isinstance(value, six.string_types):
|
elif not isinstance(value, str):
|
||||||
controls[i][1] = six.text_type(value)
|
controls[i][1] = str(value)
|
||||||
|
|
||||||
dform = self.make_deform_form()
|
dform = self.make_deform_form()
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
ul.tagit {
|
|
||||||
padding: 1px 5px;
|
|
||||||
overflow: auto;
|
|
||||||
margin-left: inherit; /* usually we don't want the regular ul margins. */
|
|
||||||
margin-right: inherit;
|
|
||||||
}
|
|
||||||
ul.tagit li {
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
margin: 2px 5px 2px 0;
|
|
||||||
}
|
|
||||||
ul.tagit li.tagit-choice {
|
|
||||||
position: relative;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
input.tagit-hidden-field {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
ul.tagit li.tagit-choice-read-only {
|
|
||||||
padding: .2em .5em .2em .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.tagit li.tagit-choice-editable {
|
|
||||||
padding: .2em 18px .2em .5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.tagit li.tagit-new {
|
|
||||||
padding: .25em 4px .25em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.tagit li.tagit-choice a.tagit-label {
|
|
||||||
cursor: pointer;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
ul.tagit li.tagit-choice .tagit-close {
|
|
||||||
cursor: pointer;
|
|
||||||
position: absolute;
|
|
||||||
right: .1em;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -8px;
|
|
||||||
line-height: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* used for some custom themes that don't need image icons */
|
|
||||||
ul.tagit li.tagit-choice .tagit-close .text-icon {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.tagit li.tagit-choice input {
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
margin: 2px 5px 2px 0;
|
|
||||||
}
|
|
||||||
ul.tagit input[type="text"] {
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
-moz-box-shadow: none;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: inherit;
|
|
||||||
background-color: inherit;
|
|
||||||
outline: none;
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
|
|
||||||
/******************************
|
|
||||||
* login.css
|
|
||||||
******************************/
|
|
||||||
|
|
||||||
.logo img,
|
|
||||||
#logo {
|
|
||||||
display: block;
|
|
||||||
margin: 40px auto;
|
|
||||||
max-height: 350px;
|
|
||||||
max-width: 800px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.form {
|
|
||||||
margin: auto;
|
|
||||||
float: none;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.field-wrapper {
|
|
||||||
margin: 10px auto;
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.field-wrapper label {
|
|
||||||
text-align: right;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.field-wrapper div.field input[type="text"],
|
|
||||||
div.field-wrapper div.field input[type="password"] {
|
|
||||||
margin-left: 1em;
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.buttons {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.buttons input {
|
|
||||||
margin: auto 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this is for "login as chuck" tip in demo mode */
|
|
||||||
.tips {
|
|
||||||
margin-top: 2em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
17
tailbone/static/js/lib/tag-it.min.js
vendored
17
tailbone/static/js/lib/tag-it.min.js
vendored
|
@ -1,17 +0,0 @@
|
||||||
(function(b){b.widget("ui.tagit",{options:{allowDuplicates:!1,caseSensitive:!0,fieldName:"tags",placeholderText:null,readOnly:!1,removeConfirmation:!1,tagLimit:null,availableTags:[],autocomplete:{},showAutocompleteOnFocus:!1,allowSpaces:!1,singleField:!1,singleFieldDelimiter:",",singleFieldNode:null,animate:!0,tabIndex:null,beforeTagAdded:null,afterTagAdded:null,beforeTagRemoved:null,afterTagRemoved:null,onTagClicked:null,onTagLimitExceeded:null,onTagAdded:null,onTagRemoved:null,tagSource:null},_create:function(){var a=
|
|
||||||
this;this.element.is("input")?(this.tagList=b("<ul></ul>").insertAfter(this.element),this.options.singleField=!0,this.options.singleFieldNode=this.element,this.element.addClass("tagit-hidden-field")):this.tagList=this.element.find("ul, ol").andSelf().last();this.tagInput=b('<input type="text" />').addClass("ui-widget-content");this.options.readOnly&&this.tagInput.attr("disabled","disabled");this.options.tabIndex&&this.tagInput.attr("tabindex",this.options.tabIndex);this.options.placeholderText&&this.tagInput.attr("placeholder",
|
|
||||||
this.options.placeholderText);this.options.autocomplete.source||(this.options.autocomplete.source=function(a,e){var d=a.term.toLowerCase(),c=b.grep(this.options.availableTags,function(a){return 0===a.toLowerCase().indexOf(d)});this.options.allowDuplicates||(c=this._subtractArray(c,this.assignedTags()));e(c)});this.options.showAutocompleteOnFocus&&(this.tagInput.focus(function(b,d){a._showAutocomplete()}),"undefined"===typeof this.options.autocomplete.minLength&&(this.options.autocomplete.minLength=
|
|
||||||
0));b.isFunction(this.options.autocomplete.source)&&(this.options.autocomplete.source=b.proxy(this.options.autocomplete.source,this));b.isFunction(this.options.tagSource)&&(this.options.tagSource=b.proxy(this.options.tagSource,this));this.tagList.addClass("tagit").addClass("ui-widget ui-widget-content ui-corner-all").append(b('<li class="tagit-new"></li>').append(this.tagInput)).click(function(d){var c=b(d.target);c.hasClass("tagit-label")?(c=c.closest(".tagit-choice"),c.hasClass("removed")||a._trigger("onTagClicked",
|
|
||||||
d,{tag:c,tagLabel:a.tagLabel(c)})):a.tagInput.focus()});var c=!1;if(this.options.singleField)if(this.options.singleFieldNode){var d=b(this.options.singleFieldNode),f=d.val().split(this.options.singleFieldDelimiter);d.val("");b.each(f,function(b,d){a.createTag(d,null,!0);c=!0})}else this.options.singleFieldNode=b('<input type="hidden" style="display:none;" value="" name="'+this.options.fieldName+'" />'),this.tagList.after(this.options.singleFieldNode);c||this.tagList.children("li").each(function(){b(this).hasClass("tagit-new")||
|
|
||||||
(a.createTag(b(this).text(),b(this).attr("class"),!0),b(this).remove())});this.tagInput.keydown(function(c){if(c.which==b.ui.keyCode.BACKSPACE&&""===a.tagInput.val()){var d=a._lastTag();!a.options.removeConfirmation||d.hasClass("remove")?a.removeTag(d):a.options.removeConfirmation&&d.addClass("remove ui-state-highlight")}else a.options.removeConfirmation&&a._lastTag().removeClass("remove ui-state-highlight");if(c.which===b.ui.keyCode.COMMA&&!1===c.shiftKey||c.which===b.ui.keyCode.ENTER||c.which==
|
|
||||||
b.ui.keyCode.TAB&&""!==a.tagInput.val()||c.which==b.ui.keyCode.SPACE&&!0!==a.options.allowSpaces&&('"'!=b.trim(a.tagInput.val()).replace(/^s*/,"").charAt(0)||'"'==b.trim(a.tagInput.val()).charAt(0)&&'"'==b.trim(a.tagInput.val()).charAt(b.trim(a.tagInput.val()).length-1)&&0!==b.trim(a.tagInput.val()).length-1))c.which===b.ui.keyCode.ENTER&&""===a.tagInput.val()||c.preventDefault(),a.options.autocomplete.autoFocus&&a.tagInput.data("autocomplete-open")||(a.tagInput.autocomplete("close"),a.createTag(a._cleanedInput()))}).blur(function(b){a.tagInput.data("autocomplete-open")||
|
|
||||||
a.createTag(a._cleanedInput())});if(this.options.availableTags||this.options.tagSource||this.options.autocomplete.source)d={select:function(b,c){a.createTag(c.item.value);return!1}},b.extend(d,this.options.autocomplete),d.source=this.options.tagSource||d.source,this.tagInput.autocomplete(d).bind("autocompleteopen.tagit",function(b,c){a.tagInput.data("autocomplete-open",!0)}).bind("autocompleteclose.tagit",function(b,c){a.tagInput.data("autocomplete-open",!1)}),this.tagInput.autocomplete("widget").addClass("tagit-autocomplete")},
|
|
||||||
destroy:function(){b.Widget.prototype.destroy.call(this);this.element.unbind(".tagit");this.tagList.unbind(".tagit");this.tagInput.removeData("autocomplete-open");this.tagList.removeClass("tagit ui-widget ui-widget-content ui-corner-all tagit-hidden-field");this.element.is("input")?(this.element.removeClass("tagit-hidden-field"),this.tagList.remove()):(this.element.children("li").each(function(){b(this).hasClass("tagit-new")?b(this).remove():(b(this).removeClass("tagit-choice ui-widget-content ui-state-default ui-state-highlight ui-corner-all remove tagit-choice-editable tagit-choice-read-only"),
|
|
||||||
b(this).text(b(this).children(".tagit-label").text()))}),this.singleFieldNode&&this.singleFieldNode.remove());return this},_cleanedInput:function(){return b.trim(this.tagInput.val().replace(/^"(.*)"$/,"$1"))},_lastTag:function(){return this.tagList.find(".tagit-choice:last:not(.removed)")},_tags:function(){return this.tagList.find(".tagit-choice:not(.removed)")},assignedTags:function(){var a=this,c=[];this.options.singleField?(c=b(this.options.singleFieldNode).val().split(this.options.singleFieldDelimiter),
|
|
||||||
""===c[0]&&(c=[])):this._tags().each(function(){c.push(a.tagLabel(this))});return c},_updateSingleTagsField:function(a){b(this.options.singleFieldNode).val(a.join(this.options.singleFieldDelimiter)).trigger("change")},_subtractArray:function(a,c){for(var d=[],f=0;f<a.length;f++)-1==b.inArray(a[f],c)&&d.push(a[f]);return d},tagLabel:function(a){return this.options.singleField?b(a).find(".tagit-label:first").text():b(a).find("input:first").val()},_showAutocomplete:function(){this.tagInput.autocomplete("search",
|
|
||||||
"")},_findTagByLabel:function(a){var c=this,d=null;this._tags().each(function(f){if(c._formatStr(a)==c._formatStr(c.tagLabel(this)))return d=b(this),!1});return d},_isNew:function(a){return!this._findTagByLabel(a)},_formatStr:function(a){return this.options.caseSensitive?a:b.trim(a.toLowerCase())},_effectExists:function(a){return Boolean(b.effects&&(b.effects[a]||b.effects.effect&&b.effects.effect[a]))},createTag:function(a,c,d){var f=this;a=b.trim(a);this.options.preprocessTag&&(a=this.options.preprocessTag(a));
|
|
||||||
if(""===a)return!1;if(!this.options.allowDuplicates&&!this._isNew(a))return a=this._findTagByLabel(a),!1!==this._trigger("onTagExists",null,{existingTag:a,duringInitialization:d})&&this._effectExists("highlight")&&a.effect("highlight"),!1;if(this.options.tagLimit&&this._tags().length>=this.options.tagLimit)return this._trigger("onTagLimitExceeded",null,{duringInitialization:d}),!1;var g=b(this.options.onTagClicked?'<a class="tagit-label"></a>':'<span class="tagit-label"></span>').text(a),e=b("<li></li>").addClass("tagit-choice ui-widget-content ui-state-default ui-corner-all").addClass(c).append(g);
|
|
||||||
this.options.readOnly?e.addClass("tagit-choice-read-only"):(e.addClass("tagit-choice-editable"),c=b("<span></span>").addClass("ui-icon ui-icon-close"),c=b('<a><span class="text-icon">\u00d7</span></a>').addClass("tagit-close").append(c).click(function(a){f.removeTag(e)}),e.append(c));this.options.singleField||(g=g.html(),e.append('<input type="hidden" value="'+g+'" name="'+this.options.fieldName+'" class="tagit-hidden-field" />'));!1!==this._trigger("beforeTagAdded",null,{tag:e,tagLabel:this.tagLabel(e),
|
|
||||||
duringInitialization:d})&&(this.options.singleField&&(g=this.assignedTags(),g.push(a),this._updateSingleTagsField(g)),this._trigger("onTagAdded",null,e),this.tagInput.val(""),this.tagInput.parent().before(e),this._trigger("afterTagAdded",null,{tag:e,tagLabel:this.tagLabel(e),duringInitialization:d}),this.options.showAutocompleteOnFocus&&!d&&setTimeout(function(){f._showAutocomplete()},0))},removeTag:function(a,c){c="undefined"===typeof c?this.options.animate:c;a=b(a);this._trigger("onTagRemoved",
|
|
||||||
null,a);if(!1!==this._trigger("beforeTagRemoved",null,{tag:a,tagLabel:this.tagLabel(a)})){if(this.options.singleField){var d=this.assignedTags(),f=this.tagLabel(a),d=b.grep(d,function(a){return a!=f});this._updateSingleTagsField(d)}if(c){a.addClass("removed");var d=this._effectExists("blind")?["blind",{direction:"horizontal"},"fast"]:["fast"],g=this;d.push(function(){a.remove();g._trigger("afterTagRemoved",null,{tag:a,tagLabel:g.tagLabel(a)})});a.fadeOut("fast").hide.apply(a,d).dequeue()}else a.remove(),
|
|
||||||
this._trigger("afterTagRemoved",null,{tag:a,tagLabel:this.tagLabel(a)})}},removeTagByLabel:function(a,b){var d=this._findTagByLabel(a);if(!d)throw"No such tag exists with the name '"+a+"'";this.removeTag(d,b)},removeAll:function(){var a=this;this._tags().each(function(b,d){a.removeTag(d,!1)})}})})(jQuery);
|
|
|
@ -1,32 +0,0 @@
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('input[name="username"]').keydown(function(event) {
|
|
||||||
if (event.which == 13) {
|
|
||||||
$('input[name="password"]').focus().select();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('form').submit(function() {
|
|
||||||
if (! $('input[name="username"]').val()) {
|
|
||||||
with ($('input[name="username"]').get(0)) {
|
|
||||||
select();
|
|
||||||
focus();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (! $('input[name="password"]').val()) {
|
|
||||||
with ($('input[name="password"]').get(0)) {
|
|
||||||
select();
|
|
||||||
focus();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('input[name="username"]').focus();
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,29 +0,0 @@
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
*
|
|
||||||
* tailbone.appsettings.js
|
|
||||||
*
|
|
||||||
* Logic for App Settings page.
|
|
||||||
*
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
function show_group(group) {
|
|
||||||
if (group == "(All)") {
|
|
||||||
$('.panel').show();
|
|
||||||
} else {
|
|
||||||
$('.panel').hide();
|
|
||||||
$('.panel[data-groupname="' + group + '"]').show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#settings-group').on('selectmenuchange', function(event, ui) {
|
|
||||||
show_group(ui.item.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
show_group($('#settings-group').val());
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,41 +0,0 @@
|
||||||
|
|
||||||
/************************************************************
|
|
||||||
*
|
|
||||||
* tailbone.batch.js
|
|
||||||
*
|
|
||||||
* Common logic for view/edit batch pages
|
|
||||||
*
|
|
||||||
************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#execute-batch').click(function() {
|
|
||||||
if (has_execution_options) {
|
|
||||||
$('#execution-options-dialog').dialog({
|
|
||||||
title: "Execution Options",
|
|
||||||
width: 600,
|
|
||||||
modal: true,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "Execute",
|
|
||||||
click: function(event) {
|
|
||||||
dialog_button(event).button('option', 'label', "Executing, please wait...").button('disable');
|
|
||||||
$('form[name="batch-execution"]').submit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
click: function() {
|
|
||||||
$(this).dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$(this).button('option', 'label', "Executing, please wait...").button('disable');
|
|
||||||
$('form[name="batch-execution"]').submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
|
@ -24,8 +24,6 @@
|
||||||
Event Subscribers
|
Event Subscribers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -42,7 +40,7 @@ from tailbone import helpers
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.config import csrf_header_name, should_expose_websockets
|
from tailbone.config import csrf_header_name, should_expose_websockets
|
||||||
from tailbone.menus import make_simple_menus
|
from tailbone.menus import make_simple_menus
|
||||||
from tailbone.util import should_use_buefy, get_global_search_options
|
from tailbone.util import get_global_search_options
|
||||||
|
|
||||||
|
|
||||||
def new_request(event):
|
def new_request(event):
|
||||||
|
@ -156,23 +154,20 @@ def before_render(event):
|
||||||
renderer_globals['background_color'] = request.rattail_config.get(
|
renderer_globals['background_color'] = request.rattail_config.get(
|
||||||
'tailbone', 'background_color')
|
'tailbone', 'background_color')
|
||||||
|
|
||||||
# buefy themes get some extra treatment
|
# TODO: remove this hack once nothing references it
|
||||||
if should_use_buefy(request):
|
renderer_globals['buefy_0_8'] = False
|
||||||
|
|
||||||
# TODO: remove this hack once nothing references it
|
# maybe set custom stylesheet
|
||||||
renderer_globals['buefy_0_8'] = False
|
css = None
|
||||||
|
if request.user:
|
||||||
|
css = request.rattail_config.get('tailbone.{}'.format(request.user.uuid),
|
||||||
|
'buefy_css')
|
||||||
|
if not css:
|
||||||
|
css = request.rattail_config.get('tailbone', 'theme.falafel.buefy_css')
|
||||||
|
renderer_globals['buefy_css'] = css
|
||||||
|
|
||||||
# maybe set custom stylesheet
|
# add global search data for quick access
|
||||||
css = None
|
renderer_globals['global_search_data'] = get_global_search_options(request)
|
||||||
if request.user:
|
|
||||||
css = request.rattail_config.get('tailbone.{}'.format(request.user.uuid),
|
|
||||||
'buefy_css')
|
|
||||||
if not css:
|
|
||||||
css = request.rattail_config.get('tailbone', 'theme.falafel.buefy_css')
|
|
||||||
renderer_globals['buefy_css'] = css
|
|
||||||
|
|
||||||
# add global search data for quick access
|
|
||||||
renderer_globals['global_search_data'] = get_global_search_options(request)
|
|
||||||
|
|
||||||
# here we globally declare widths for grid filter pseudo-columns
|
# here we globally declare widths for grid filter pseudo-columns
|
||||||
widths = request.rattail_config.get('tailbone', 'grids.filters.column_widths')
|
widths = request.rattail_config.get('tailbone', 'grids.filters.column_widths')
|
||||||
|
|
|
@ -5,34 +5,6 @@
|
||||||
|
|
||||||
<%def name="content_title()"></%def>
|
<%def name="content_title()"></%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.appsettings.js') + '?ver={}'.format(tailbone.__version__))}
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
|
||||||
${parent.extra_styles()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<style type="text/css">
|
|
||||||
div.form {
|
|
||||||
float: none;
|
|
||||||
}
|
|
||||||
div.panel {
|
|
||||||
width: 85%;
|
|
||||||
}
|
|
||||||
.field-wrapper {
|
|
||||||
margin-bottom: 2em;
|
|
||||||
}
|
|
||||||
.panel .field-wrapper label {
|
|
||||||
font-family: monospace;
|
|
||||||
width: 50em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
% if request.has_perm('settings.list'):
|
% if request.has_perm('settings.list'):
|
||||||
<li>${h.link_to("View Raw Settings", url('settings'))}</li>
|
<li>${h.link_to("View Raw Settings", url('settings'))}</li>
|
||||||
|
@ -223,76 +195,4 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
% if use_buefy:
|
${parent.body()}
|
||||||
${parent.body()}
|
|
||||||
|
|
||||||
% else:
|
|
||||||
## legacy / not buefy
|
|
||||||
<div class="form">
|
|
||||||
${h.form(form.action_url, id=dform.formid, method='post', class_='autodisable')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
|
|
||||||
% if dform.error:
|
|
||||||
<div class="error-messages">
|
|
||||||
<div class="ui-state-error ui-corner-all">
|
|
||||||
<span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-alert"></span>
|
|
||||||
Please see errors below.
|
|
||||||
</div>
|
|
||||||
<div class="ui-state-error ui-corner-all">
|
|
||||||
<span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-alert"></span>
|
|
||||||
${dform.error}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
<div class="group-picker">
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label for="settings-group">Showing Group</label>
|
|
||||||
<div class="field select">
|
|
||||||
${h.select('settings-group', current_group, group_options, **{'auto-enhance': 'true'})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% for group in groups:
|
|
||||||
<div class="panel" data-groupname="${group}">
|
|
||||||
<h2>${group}</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
|
|
||||||
% for setting in settings:
|
|
||||||
% if setting.group == group:
|
|
||||||
<% field = dform[setting.node_name] %>
|
|
||||||
|
|
||||||
<div class="field-wrapper ${field.name} ${'with-error' if field.error else ''}">
|
|
||||||
% if field.error:
|
|
||||||
<div class="field-error">
|
|
||||||
% for msg in field.error.messages():
|
|
||||||
<span class="error-msg">${msg}</span>
|
|
||||||
% endfor
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
<div class="field-row">
|
|
||||||
<label for="${field.oid}">${form.get_label(field.name)}</label>
|
|
||||||
<div class="field">
|
|
||||||
${field.serialize()|n}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% if form.has_helptext(field.name):
|
|
||||||
<span class="instructions">${form.render_helptext(field.name)}</span>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
</div><!-- panel-body -->
|
|
||||||
</div><! -- panel -->
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
${h.submit('save', getattr(form, 'submit_label', getattr(form, 'save_label', "Submit")), class_='button is-primary')}
|
|
||||||
${h.link_to("Cancel", form.cancel_url, class_='cancel button{}'.format(' autodisable' if form.auto_disable_cancel else ''))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${h.end_form()}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
|
@ -76,12 +76,5 @@
|
||||||
</div>
|
</div>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form()">
|
|
||||||
${parent.render_form()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${self.field_diff_table()}
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -1,150 +1,66 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/index.mako" />
|
<%inherit file="/master/index.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
% if master.results_executable and master.has_perm('execute_multiple'):
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var has_execution_options = ${'true' if master.has_execution_options(batch) else 'false'};
|
|
||||||
var dialog_opened = false;
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#refresh-results-button').click(function() {
|
|
||||||
var count = $('.grid-wrapper').gridwrapper('results_count');
|
|
||||||
if (!count) {
|
|
||||||
alert("There are no batch results to refresh.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var form = $('form[name="refresh-results"]');
|
|
||||||
$(this).button('option', 'label', "Refreshing, please wait...").button('disable');
|
|
||||||
form.submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#execute-results-button').click(function() {
|
|
||||||
var count = $('.grid-wrapper').gridwrapper('results_count');
|
|
||||||
if (!count) {
|
|
||||||
alert("There are no batch results to execute.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var form = $('form[name="execute-results"]');
|
|
||||||
if (has_execution_options) {
|
|
||||||
$('#execution-options-dialog').dialog({
|
|
||||||
title: "Execution Options",
|
|
||||||
width: 550,
|
|
||||||
height: 300,
|
|
||||||
modal: true,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "Execute",
|
|
||||||
click: function(event) {
|
|
||||||
dialog_button(event).button('option', 'label', "Executing, please wait...").button('disable');
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
click: function() {
|
|
||||||
$(this).dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
open: function() {
|
|
||||||
if (! dialog_opened) {
|
|
||||||
$('#execution-options-dialog select[auto-enhance="true"]').selectmenu();
|
|
||||||
$('#execution-options-dialog select[auto-enhance="true"]').on('selectmenuopen', function(event, ui) {
|
|
||||||
show_all_options($(this));
|
|
||||||
});
|
|
||||||
dialog_opened = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$(this).button('option', 'label', "Executing, please wait...").button('disable');
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="grid_tools()">
|
<%def name="grid_tools()">
|
||||||
${parent.grid_tools()}
|
${parent.grid_tools()}
|
||||||
|
|
||||||
## Refresh Results
|
## Refresh Results
|
||||||
% if master.results_refreshable and master.has_perm('refresh'):
|
% if master.results_refreshable and master.has_perm('refresh'):
|
||||||
% if use_buefy:
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
:disabled="refreshResultsButtonDisabled"
|
||||||
:disabled="refreshResultsButtonDisabled"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="fas fa-redo"
|
||||||
icon-left="fas fa-redo"
|
@click="refreshResults()">
|
||||||
@click="refreshResults()">
|
{{ refreshResultsButtonText }}
|
||||||
{{ refreshResultsButtonText }}
|
</b-button>
|
||||||
</b-button>
|
${h.form(url('{}.refresh_results'.format(route_prefix)), ref='refreshResultsForm')}
|
||||||
${h.form(url('{}.refresh_results'.format(route_prefix)), ref='refreshResultsForm')}
|
${h.csrf_token(request)}
|
||||||
${h.csrf_token(request)}
|
${h.end_form()}
|
||||||
${h.end_form()}
|
|
||||||
% else:
|
|
||||||
<button type="button" id="refresh-results-button">
|
|
||||||
Refresh Results
|
|
||||||
</button>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## Execute Results
|
## Execute Results
|
||||||
% if master.results_executable and master.has_perm('execute_multiple'):
|
% if master.results_executable and master.has_perm('execute_multiple'):
|
||||||
% if use_buefy:
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
@click="executeResults()"
|
||||||
@click="executeResults()"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="arrow-circle-right"
|
||||||
icon-left="arrow-circle-right"
|
:disabled="!total">
|
||||||
:disabled="!total">
|
Execute Results
|
||||||
Execute Results
|
</b-button>
|
||||||
</b-button>
|
|
||||||
|
|
||||||
<b-modal has-modal-card
|
<b-modal has-modal-card
|
||||||
:active.sync="showExecutionOptions">
|
:active.sync="showExecutionOptions">
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
|
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">Execution Options</p>
|
<p class="modal-card-title">Execution Options</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="modal-card-body">
|
|
||||||
<p>
|
|
||||||
Please be advised, you are about to execute {{ total }} batches!
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<div class="form-wrapper">
|
|
||||||
<div class="form">
|
|
||||||
<${execute_form.component} ref="executeResultsForm"></${execute_form.component}>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<footer class="modal-card-foot">
|
|
||||||
<b-button @click="showExecutionOptions = false">
|
|
||||||
Cancel
|
|
||||||
</b-button>
|
|
||||||
<once-button type="is-primary"
|
|
||||||
@click="submitExecuteResults()"
|
|
||||||
icon-left="arrow-circle-right"
|
|
||||||
:text="'Execute ' + total + ' Batches'">
|
|
||||||
</once-button>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<p>
|
||||||
|
Please be advised, you are about to execute {{ total }} batches!
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<div class="form-wrapper">
|
||||||
|
<div class="form">
|
||||||
|
<${execute_form.component} ref="executeResultsForm"></${execute_form.component}>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
</section>
|
||||||
|
|
||||||
% else:
|
<footer class="modal-card-foot">
|
||||||
<button type="button" id="execute-results-button">Execute Results</button>
|
<b-button @click="showExecutionOptions = false">
|
||||||
% endif
|
Cancel
|
||||||
|
</b-button>
|
||||||
|
<once-button type="is-primary"
|
||||||
|
@click="submitExecuteResults()"
|
||||||
|
icon-left="arrow-circle-right"
|
||||||
|
:text="'Execute ' + total + ' Batches'">
|
||||||
|
</once-button>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</b-modal>
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -224,24 +140,3 @@
|
||||||
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
||||||
% if not use_buefy:
|
|
||||||
|
|
||||||
## Refresh Results
|
|
||||||
% if master.results_refreshable and master.has_perm('refresh'):
|
|
||||||
${h.form(url('{}.refresh_results'.format(route_prefix)), name='refresh-results')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if master.results_executable and master.has_perm('execute_multiple'):
|
|
||||||
<div id="execution-options-dialog" style="display: none;">
|
|
||||||
<br />
|
|
||||||
<p>
|
|
||||||
Please be advised, you are about to execute multiple batches!
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
${execute_form.render_deform(form_kwargs={'name': 'execute-results'}, buttons=False)|n}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
|
|
|
@ -3,298 +3,67 @@
|
||||||
|
|
||||||
<%def name="title()">Inventory Form</%def>
|
<%def name="title()">Inventory Form</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/numeric.js'))}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function assert_quantity() {
|
|
||||||
% if allow_cases:
|
|
||||||
var cases = parseFloat($('#cases').val());
|
|
||||||
if (!isNaN(cases)) {
|
|
||||||
if (cases > 999999) {
|
|
||||||
alert("Case amount is invalid!");
|
|
||||||
$('#cases').select().focus();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
var units = parseFloat($('#units').val());
|
|
||||||
if (!isNaN(units)) {
|
|
||||||
if (units > 999999) {
|
|
||||||
alert("Unit amount is invalid!");
|
|
||||||
$('#units').select().focus();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
alert("Please provide case and/or unit quantity");
|
|
||||||
% if allow_cases:
|
|
||||||
$('#cases').select().focus();
|
|
||||||
% else:
|
|
||||||
$('#units').select().focus();
|
|
||||||
% endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalid_product(msg) {
|
|
||||||
$('#product-info p').text(msg);
|
|
||||||
$('#product-info img').hide();
|
|
||||||
$('#upc').focus().select();
|
|
||||||
% if allow_cases:
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', true);
|
|
||||||
% endif
|
|
||||||
$('.field-wrapper.units input').prop('disabled', true);
|
|
||||||
$('.buttons button').button('disable');
|
|
||||||
}
|
|
||||||
|
|
||||||
function pretty_quantity(cases, units) {
|
|
||||||
if (cases && units) {
|
|
||||||
return cases + " cases, " + units + " units";
|
|
||||||
} else if (cases) {
|
|
||||||
return cases + " cases";
|
|
||||||
} else if (units) {
|
|
||||||
return units + " units";
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function show_quantity(name, cases, units) {
|
|
||||||
var quantity = pretty_quantity(cases, units);
|
|
||||||
var field = $('.field-wrapper.quantity_' + name);
|
|
||||||
field.find('.field').text(quantity);
|
|
||||||
if (quantity || name == 'ordered') {
|
|
||||||
field.show();
|
|
||||||
} else {
|
|
||||||
field.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#upc').keydown(function(event) {
|
|
||||||
|
|
||||||
if (key_allowed(event)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (key_modifies(event)) {
|
|
||||||
$('#product').val('');
|
|
||||||
$('#product-info p').html("please ENTER a scancode");
|
|
||||||
$('#product-info img').hide();
|
|
||||||
$('#product-info .warning').hide();
|
|
||||||
$('.product-fields').hide();
|
|
||||||
// $('.receiving-fields').hide();
|
|
||||||
% if allow_cases:
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', true);
|
|
||||||
% endif
|
|
||||||
$('.field-wrapper.units input').prop('disabled', true);
|
|
||||||
$('.buttons button').button('disable');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when user presses ENTER, do product lookup
|
|
||||||
if (event.which == 13) {
|
|
||||||
var upc = $(this).val();
|
|
||||||
var data = {'upc': upc};
|
|
||||||
$.get('${url('batch.inventory.desktop_lookup', uuid=batch.uuid)}', data, function(data) {
|
|
||||||
|
|
||||||
if (data.error) {
|
|
||||||
alert(data.error);
|
|
||||||
if (data.redirect) {
|
|
||||||
$('#inventory-form').mask("Redirecting...");
|
|
||||||
location.href = data.redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (data.product) {
|
|
||||||
$('#upc').val(data.product.upc_pretty);
|
|
||||||
$('#product').val(data.product.uuid);
|
|
||||||
$('#brand_name').val(data.product.brand_name);
|
|
||||||
$('#description').val(data.product.description);
|
|
||||||
$('#size').val(data.product.size);
|
|
||||||
$('#case_quantity').val(data.product.case_quantity);
|
|
||||||
|
|
||||||
if (data.force_unit_item) {
|
|
||||||
$('#product-info .warning.force-unit').show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.already_present_in_batch) {
|
|
||||||
$('#product-info .warning.present').show();
|
|
||||||
$('#cases').val(data.cases);
|
|
||||||
$('#units').val(data.units);
|
|
||||||
|
|
||||||
} else if (data.product.type2) {
|
|
||||||
$('#units').val(data.product.units);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#product-info p').text(data.product.full_description);
|
|
||||||
$('#product-info img').attr('src', data.product.image_url).show();
|
|
||||||
if (! data.product.uuid) {
|
|
||||||
// $('#product-info .warning.notfound').show();
|
|
||||||
$('.product-fields').show();
|
|
||||||
}
|
|
||||||
$('#product-info .warning.notordered').show();
|
|
||||||
% if allow_cases:
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', false);
|
|
||||||
% endif
|
|
||||||
$('.field-wrapper.units input').prop('disabled', false);
|
|
||||||
$('.buttons button').button('enable');
|
|
||||||
|
|
||||||
if (data.product.type2) {
|
|
||||||
$('#units').focus().select();
|
|
||||||
} else {
|
|
||||||
% if allow_cases and prefer_cases:
|
|
||||||
if ($('#cases').val()) {
|
|
||||||
$('#cases').focus().select();
|
|
||||||
} else if ($('#units').val()) {
|
|
||||||
$('#units').focus().select();
|
|
||||||
} else {
|
|
||||||
$('#cases').focus().select();
|
|
||||||
}
|
|
||||||
% else:
|
|
||||||
$('#units').focus().select();
|
|
||||||
% endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this is maybe useful if "new products" may be added via inventory batch
|
|
||||||
// } else if (data.upc) {
|
|
||||||
// $('#upc').val(data.upc_pretty);
|
|
||||||
// $('#product-info p').text("product not found in our system");
|
|
||||||
// $('#product-info img').attr('src', data.image_url).show();
|
|
||||||
|
|
||||||
// $('#product').val('');
|
|
||||||
// $('#brand_name').val('');
|
|
||||||
// $('#description').val('');
|
|
||||||
// $('#size').val('');
|
|
||||||
// $('#case_quantity').val('');
|
|
||||||
|
|
||||||
// $('#product-info .warning.notfound').show();
|
|
||||||
// $('.product-fields').show();
|
|
||||||
// $('#brand_name').focus();
|
|
||||||
// $('.field-wrapper.cases input').prop('disabled', false);
|
|
||||||
// $('.field-wrapper.units input').prop('disabled', false);
|
|
||||||
// $('.buttons button').button('enable');
|
|
||||||
|
|
||||||
} else {
|
|
||||||
invalid_product('product not found');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#inventory-form').submit(function() {
|
|
||||||
if (! assert_quantity()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
disable_submit_button(this);
|
|
||||||
$(this).mask("Working...");
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#upc').focus();
|
|
||||||
% if allow_cases:
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', true);
|
|
||||||
% endif
|
|
||||||
$('.field-wrapper.units input').prop('disabled', true);
|
|
||||||
$('.buttons button').button('disable');
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
|
||||||
${parent.extra_styles()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<style type="text/css">
|
|
||||||
|
|
||||||
#product-info {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#product-info p {
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#product-info .img-wrapper {
|
|
||||||
height: 150px;
|
|
||||||
margin: 0.5em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#product-info .warning {
|
|
||||||
background: #f66;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
${parent.context_menu_items()}
|
${parent.context_menu_items()}
|
||||||
<li>${h.link_to("Back to Inventory Batch", url('batch.inventory.view', uuid=batch.uuid))}</li>
|
<li>${h.link_to("Back to Inventory Batch", url('batch.inventory.view', uuid=batch.uuid))}</li>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form()">
|
<%def name="render_form()">
|
||||||
% if use_buefy:
|
<script type="text/x-template" id="${form.component}-template">
|
||||||
|
<div class="product-info">
|
||||||
|
|
||||||
<script type="text/x-template" id="${form.component}-template">
|
${h.form(form.action_url, **{'@submit': 'handleSubmit'})}
|
||||||
<div class="product-info">
|
${h.csrf_token(request)}
|
||||||
|
|
||||||
${h.form(form.action_url, **{'@submit': 'handleSubmit'})}
|
${h.hidden('product', **{':value': 'productInfo.uuid'})}
|
||||||
${h.csrf_token(request)}
|
${h.hidden('upc', **{':value': 'productInfo.upc'})}
|
||||||
|
${h.hidden('brand_name', **{':value': 'productInfo.brand_name'})}
|
||||||
|
${h.hidden('description', **{':value': 'productInfo.description'})}
|
||||||
|
${h.hidden('size', **{':value': 'productInfo.size'})}
|
||||||
|
${h.hidden('case_quantity', **{':value': 'productInfo.case_quantity'})}
|
||||||
|
|
||||||
${h.hidden('product', **{':value': 'productInfo.uuid'})}
|
<b-field label="Product UPC" horizontal>
|
||||||
${h.hidden('upc', **{':value': 'productInfo.upc'})}
|
<div style="display: flex; flex-direction: column;">
|
||||||
${h.hidden('brand_name', **{':value': 'productInfo.brand_name'})}
|
<b-input v-model="productUPC"
|
||||||
${h.hidden('description', **{':value': 'productInfo.description'})}
|
ref="productUPC"
|
||||||
${h.hidden('size', **{':value': 'productInfo.size'})}
|
@input="productChanged"
|
||||||
${h.hidden('case_quantity', **{':value': 'productInfo.case_quantity'})}
|
@keydown.native="productKeydown">
|
||||||
|
</b-input>
|
||||||
|
<div class="has-text-centered block">
|
||||||
|
|
||||||
<b-field label="Product UPC" horizontal>
|
<p v-if="!productInfo.uuid"
|
||||||
<div style="display: flex; flex-direction: column;">
|
class="block">
|
||||||
<b-input v-model="productUPC"
|
please ENTER a scancode
|
||||||
ref="productUPC"
|
</p>
|
||||||
@input="productChanged"
|
|
||||||
@keydown.native="productKeydown">
|
|
||||||
</b-input>
|
|
||||||
<div class="has-text-centered block">
|
|
||||||
|
|
||||||
<p v-if="!productInfo.uuid"
|
<p v-if="productInfo.uuid"
|
||||||
class="block">
|
class="block">
|
||||||
please ENTER a scancode
|
{{ productInfo.full_description }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p v-if="productInfo.uuid"
|
<div style="min-height: 150px; margin: 0.5rem 0;">
|
||||||
class="block">
|
<img v-if="productInfo.uuid"
|
||||||
{{ productInfo.full_description }}
|
:src="productInfo.image_url" />
|
||||||
</p>
|
</div>
|
||||||
|
|
||||||
<div style="min-height: 150px; margin: 0.5rem 0;">
|
<div v-if="alreadyPresentInBatch"
|
||||||
<img v-if="productInfo.uuid"
|
class="has-background-danger">
|
||||||
:src="productInfo.image_url" />
|
product already exists in batch, please confirm count
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="alreadyPresentInBatch"
|
<div v-if="forceUnitItem"
|
||||||
class="has-background-danger">
|
class="has-background-danger">
|
||||||
product already exists in batch, please confirm count
|
pack item scanned, but must count units instead
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="forceUnitItem"
|
|
||||||
class="has-background-danger">
|
|
||||||
pack item scanned, but must count units instead
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## <div v-if="productNotFound"
|
## <div v-if="productNotFound"
|
||||||
## class="has-background-danger">
|
## class="has-background-danger">
|
||||||
## please confirm UPC and provide more details
|
## please confirm UPC and provide more details
|
||||||
## </div>
|
## </div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
## <div v-if="productNotFound"
|
## <div v-if="productNotFound"
|
||||||
## ## class="product-fields"
|
## ## class="product-fields"
|
||||||
|
@ -322,243 +91,176 @@
|
||||||
##
|
##
|
||||||
## </div>
|
## </div>
|
||||||
|
|
||||||
% if allow_cases:
|
% if allow_cases:
|
||||||
<b-field label="Cases" horizontal>
|
<b-field label="Cases" horizontal>
|
||||||
<b-input name="cases"
|
<b-input name="cases"
|
||||||
v-model="productCases"
|
v-model="productCases"
|
||||||
ref="productCases"
|
ref="productCases"
|
||||||
:disabled="!productInfo.uuid">
|
|
||||||
</b-input>
|
|
||||||
</b-field>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
<b-field label="Units" horizontal>
|
|
||||||
<b-input name="units"
|
|
||||||
v-model="productUnits"
|
|
||||||
ref="productUnits"
|
|
||||||
:disabled="!productInfo.uuid">
|
:disabled="!productInfo.uuid">
|
||||||
</b-input>
|
</b-input>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
% endif
|
||||||
|
|
||||||
<b-button type="is-primary"
|
<b-field label="Units" horizontal>
|
||||||
native-type="submit"
|
<b-input name="units"
|
||||||
:disabled="submitting">
|
v-model="productUnits"
|
||||||
{{ submitting ? "Working, please wait..." : "Submit" }}
|
ref="productUnits"
|
||||||
</b-button>
|
:disabled="!productInfo.uuid">
|
||||||
|
</b-input>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
${h.end_form()}
|
<b-button type="is-primary"
|
||||||
</div>
|
native-type="submit"
|
||||||
</script>
|
:disabled="submitting">
|
||||||
|
{{ submitting ? "Working, please wait..." : "Submit" }}
|
||||||
|
</b-button>
|
||||||
|
|
||||||
<script type="text/javascript">
|
${h.end_form()}
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
let ${form.component_studly} = {
|
<script type="text/javascript">
|
||||||
template: '#${form.component}-template',
|
|
||||||
|
|
||||||
mounted() {
|
let ${form.component_studly} = {
|
||||||
this.$refs.productUPC.focus()
|
template: '#${form.component}-template',
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$refs.productUPC.focus()
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
clearProduct() {
|
||||||
|
this.productInfo = {}
|
||||||
|
## this.productNotFound = false
|
||||||
|
this.alreadyPresentInBatch = false
|
||||||
|
this.forceUnitItem = false
|
||||||
|
this.productCases = null
|
||||||
|
this.productUnits = null
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
assertQuantity() {
|
||||||
|
|
||||||
clearProduct() {
|
% if allow_cases:
|
||||||
this.productInfo = {}
|
let cases = parseFloat(this.productCases)
|
||||||
## this.productNotFound = false
|
if (!isNaN(cases)) {
|
||||||
this.alreadyPresentInBatch = false
|
if (cases > 999999) {
|
||||||
this.forceUnitItem = false
|
alert("Case amount is invalid!")
|
||||||
this.productCases = null
|
this.$refs.productCases.focus()
|
||||||
this.productUnits = null
|
|
||||||
},
|
|
||||||
|
|
||||||
assertQuantity() {
|
|
||||||
|
|
||||||
% if allow_cases:
|
|
||||||
let cases = parseFloat(this.productCases)
|
|
||||||
if (!isNaN(cases)) {
|
|
||||||
if (cases > 999999) {
|
|
||||||
alert("Case amount is invalid!")
|
|
||||||
this.$refs.productCases.focus()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
|
|
||||||
let units = parseFloat(this.productUnits)
|
|
||||||
if (!isNaN(units)) {
|
|
||||||
if (units > 999999) {
|
|
||||||
alert("Unit amount is invalid!")
|
|
||||||
this.$refs.productUnits.focus()
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
% endif
|
||||||
|
|
||||||
alert("Please provide case and/or unit quantity")
|
let units = parseFloat(this.productUnits)
|
||||||
% if allow_cases:
|
if (!isNaN(units)) {
|
||||||
this.$refs.productCases.focus()
|
if (units > 999999) {
|
||||||
% else:
|
alert("Unit amount is invalid!")
|
||||||
this.$refs.productUnits.focus()
|
this.$refs.productUnits.focus()
|
||||||
% endif
|
return false
|
||||||
},
|
|
||||||
|
|
||||||
handleSubmit(event) {
|
|
||||||
if (!this.assertQuantity()) {
|
|
||||||
event.preventDefault()
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
this.submitting = true
|
return true
|
||||||
},
|
}
|
||||||
|
|
||||||
productChanged() {
|
alert("Please provide case and/or unit quantity")
|
||||||
this.clearProduct()
|
% if allow_cases:
|
||||||
},
|
this.$refs.productCases.focus()
|
||||||
|
% else:
|
||||||
productKeydown(event) {
|
this.$refs.productUnits.focus()
|
||||||
if (event.which == 13) { // ENTER
|
% endif
|
||||||
this.productLookup()
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
productLookup() {
|
|
||||||
let url = '${url('batch.inventory.desktop_lookup', uuid=batch.uuid)}'
|
|
||||||
let params = {
|
|
||||||
upc: this.productUPC,
|
|
||||||
}
|
|
||||||
this.$http.get(url, {params: params}).then(response => {
|
|
||||||
|
|
||||||
if (response.data.error) {
|
|
||||||
alert(response.data.error)
|
|
||||||
if (response.data.redirect) {
|
|
||||||
location.href = response.data.redirect
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (response.data.product.uuid) {
|
|
||||||
|
|
||||||
this.productUPC = response.data.product.upc_pretty
|
|
||||||
this.productInfo = response.data.product
|
|
||||||
this.forceUnitItem = response.data.force_unit_item
|
|
||||||
this.alreadyPresentInBatch = response.data.already_present_in_batch
|
|
||||||
|
|
||||||
if (this.alreadyPresentInBatch) {
|
|
||||||
this.productCases = response.data.cases
|
|
||||||
this.productUnits = response.data.units
|
|
||||||
} else if (this.productInfo.type2) {
|
|
||||||
this.productUnits = this.productInfo.units
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.productInfo.type2) {
|
|
||||||
this.$refs.productUnits.focus()
|
|
||||||
} else {
|
|
||||||
% if allow_cases and prefer_cases:
|
|
||||||
if (this.productCases) {
|
|
||||||
this.$refs.productCases.focus()
|
|
||||||
} else if (this.productUnits) {
|
|
||||||
this.$refs.productUnits.focus()
|
|
||||||
} else {
|
|
||||||
this.$refs.productCases.focus()
|
|
||||||
}
|
|
||||||
% else:
|
|
||||||
this.$refs.productUnits.focus()
|
|
||||||
% endif
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
} else {
|
|
||||||
## this.productNotFound = true
|
|
||||||
alert("Product not found!")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
|
||||||
|
|
||||||
let ${form.component_studly}Data = {
|
handleSubmit(event) {
|
||||||
submitting: false,
|
if (!this.assertQuantity()) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.submitting = true
|
||||||
|
},
|
||||||
|
|
||||||
productUPC: null,
|
productChanged() {
|
||||||
## productNotFound: false,
|
this.clearProduct()
|
||||||
productInfo: {},
|
},
|
||||||
|
|
||||||
% if allow_cases:
|
productKeydown(event) {
|
||||||
productCases: null,
|
if (event.which == 13) { // ENTER
|
||||||
% endif
|
this.productLookup()
|
||||||
productUnits: null,
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
alreadyPresentInBatch: false,
|
productLookup() {
|
||||||
forceUnitItem: false,
|
let url = '${url('batch.inventory.desktop_lookup', uuid=batch.uuid)}'
|
||||||
}
|
let params = {
|
||||||
|
upc: this.productUPC,
|
||||||
|
}
|
||||||
|
this.$http.get(url, {params: params}).then(response => {
|
||||||
|
|
||||||
</script>
|
if (response.data.error) {
|
||||||
|
alert(response.data.error)
|
||||||
|
if (response.data.redirect) {
|
||||||
|
location.href = response.data.redirect
|
||||||
|
}
|
||||||
|
|
||||||
% else:
|
} else if (response.data.product.uuid) {
|
||||||
## not buefy
|
|
||||||
|
|
||||||
<div class="form-wrapper">
|
this.productUPC = response.data.product.upc_pretty
|
||||||
${h.form(form.action_url, id='inventory-form')}
|
this.productInfo = response.data.product
|
||||||
${h.csrf_token(request)}
|
this.forceUnitItem = response.data.force_unit_item
|
||||||
|
this.alreadyPresentInBatch = response.data.already_present_in_batch
|
||||||
|
|
||||||
<div class="field-wrapper">
|
if (this.alreadyPresentInBatch) {
|
||||||
<label for="upc">Product UPC</label>
|
this.productCases = response.data.cases
|
||||||
<div class="field">
|
this.productUnits = response.data.units
|
||||||
${h.hidden('product')}
|
} else if (this.productInfo.type2) {
|
||||||
<div>${h.text('upc', autocomplete='off')}</div>
|
this.productUnits = this.productInfo.units
|
||||||
<div id="product-info">
|
}
|
||||||
<p>please ENTER a scancode</p>
|
|
||||||
<div class="img-wrapper"><img /></div>
|
|
||||||
<div class="warning notfound">please confirm UPC and provide more details</div>
|
|
||||||
<div class="warning present">product already exists in batch, please confirm count</div>
|
|
||||||
<div class="warning force-unit">pack item scanned, but must count units instead</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="product-fields" style="display: none;">
|
this.$nextTick(() => {
|
||||||
|
if (this.productInfo.type2) {
|
||||||
|
this.$refs.productUnits.focus()
|
||||||
|
} else {
|
||||||
|
% if allow_cases and prefer_cases:
|
||||||
|
if (this.productCases) {
|
||||||
|
this.$refs.productCases.focus()
|
||||||
|
} else if (this.productUnits) {
|
||||||
|
this.$refs.productUnits.focus()
|
||||||
|
} else {
|
||||||
|
this.$refs.productCases.focus()
|
||||||
|
}
|
||||||
|
% else:
|
||||||
|
this.$refs.productUnits.focus()
|
||||||
|
% endif
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
<div class="field-wrapper brand_name">
|
} else {
|
||||||
<label for="brand_name">Brand Name</label>
|
## this.productNotFound = true
|
||||||
<div class="field">${h.text('brand_name')}</div>
|
alert("Product not found!")
|
||||||
</div>
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
<div class="field-wrapper description">
|
let ${form.component_studly}Data = {
|
||||||
<label for="description">Description</label>
|
submitting: false,
|
||||||
<div class="field">${h.text('description')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper size">
|
productUPC: null,
|
||||||
<label for="size">Size</label>
|
## productNotFound: false,
|
||||||
<div class="field">${h.text('size')}</div>
|
productInfo: {},
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper case_quantity">
|
|
||||||
<label for="case_quantity">Units in Case</label>
|
|
||||||
<div class="field">${h.text('case_quantity')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% if allow_cases:
|
% if allow_cases:
|
||||||
<div class="field-wrapper cases">
|
productCases: null,
|
||||||
<label for="cases">Cases</label>
|
|
||||||
<div class="field">${h.text('cases', autocomplete='off')}</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
% endif
|
||||||
|
productUnits: null,
|
||||||
|
|
||||||
<div class="field-wrapper units">
|
alreadyPresentInBatch: false,
|
||||||
<label for="units">Units</label>
|
forceUnitItem: false,
|
||||||
<div class="field">${h.text('units', autocomplete='off')}</div>
|
}
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="buttons">
|
</script>
|
||||||
${h.submit('submit', "Submit")}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${h.end_form()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,59 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/batch/create.mako" />
|
<%inherit file="/batch/create.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var vendormap = {
|
|
||||||
% for i, parser in enumerate(parsers, 1):
|
|
||||||
'${parser.key}': ${parser.vendormap_value|n}${',' if i < len(parsers) else ''}
|
|
||||||
% endfor
|
|
||||||
};
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
if ($('select[name="parser_key"] option:first').is(':selected')) {
|
|
||||||
$('.vendor_uuid .autocomplete-container').hide();
|
|
||||||
} else {
|
|
||||||
$('.vendor_uuid input[name="vendor_uuid"]').val('');
|
|
||||||
$('.vendor_uuid .autocomplete-display').hide();
|
|
||||||
$('.vendor_uuid .autocomplete-display button').show();
|
|
||||||
$('.vendor_uuid .autocomplete-textbox').val('');
|
|
||||||
$('.vendor_uuid .autocomplete-textbox').show();
|
|
||||||
$('.vendor_uuid .autocomplete-container').show();
|
|
||||||
}
|
|
||||||
|
|
||||||
$('select[name="parser_key"]').on('selectmenuchange', function() {
|
|
||||||
if ($(this).find('option:first').is(':selected')) {
|
|
||||||
$('.vendor_uuid .autocomplete-container').hide();
|
|
||||||
} else {
|
|
||||||
var vendor = vendormap[$(this).val()];
|
|
||||||
if (vendor) {
|
|
||||||
$('.vendor_uuid input[name="vendor_uuid"]').val(vendor.uuid);
|
|
||||||
$('.vendor_uuid .autocomplete-textbox').hide();
|
|
||||||
$('.vendor_uuid .autocomplete-display span:first').text(vendor.name);
|
|
||||||
$('.vendor_uuid .autocomplete-display button').hide();
|
|
||||||
$('.vendor_uuid .autocomplete-display').show();
|
|
||||||
$('.vendor_uuid .autocomplete-container').show();
|
|
||||||
} else {
|
|
||||||
$('.vendor_uuid input[name="vendor_uuid"]').val('');
|
|
||||||
$('.vendor_uuid .autocomplete-display').hide();
|
|
||||||
$('.vendor_uuid .autocomplete-display button').show();
|
|
||||||
$('.vendor_uuid .autocomplete-textbox').val('');
|
|
||||||
$('.vendor_uuid .autocomplete-textbox').show();
|
|
||||||
$('.vendor_uuid .autocomplete-container').show();
|
|
||||||
$('.vendor_uuid .autocomplete-textbox').focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
${parent.modify_this_page_vars()}
|
${parent.modify_this_page_vars()}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
@ -1,68 +1,8 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.batch.js') + '?ver={}'.format(tailbone.__version__))}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var has_execution_options = ${'true' if master.has_execution_options(batch) else 'false'};
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
% if master.has_worksheet and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
|
||||||
$('.load-worksheet').click(function() {
|
|
||||||
disable_button(this);
|
|
||||||
location.href = '${url('{}.worksheet'.format(route_prefix), uuid=batch.uuid)}';
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
% if master.batch_refreshable(batch) and master.has_perm('refresh'):
|
|
||||||
$('#refresh-data').click(function() {
|
|
||||||
$(this)
|
|
||||||
.button('option', 'disabled', true)
|
|
||||||
.button('option', 'label', "Working, please wait...");
|
|
||||||
location.href = '${url('{}.refresh'.format(route_prefix), uuid=batch.uuid)}';
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
% if master.has_worksheet_file and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
|
||||||
$('.upload-worksheet').click(function() {
|
|
||||||
$('#upload-worksheet-dialog').dialog({
|
|
||||||
title: "Upload Worksheet",
|
|
||||||
width: 600,
|
|
||||||
modal: true,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "Upload & Update Batch",
|
|
||||||
click: function(event) {
|
|
||||||
var form = $('form[name="upload-worksheet"]');
|
|
||||||
var field = form.find('input[type="file"]').get(0);
|
|
||||||
if (!field.value) {
|
|
||||||
alert("Please choose a file to upload.");
|
|
||||||
return
|
|
||||||
}
|
|
||||||
disable_button(dialog_button(event));
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
click: function() {
|
|
||||||
$(this).dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if use_buefy:
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
|
||||||
.modal-card-body label {
|
.modal-card-body label {
|
||||||
|
@ -74,19 +14,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
% else:
|
|
||||||
<style type="text/css">
|
|
||||||
|
|
||||||
.grid-wrapper {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.complete form {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="buttons()">
|
<%def name="buttons()">
|
||||||
|
@ -99,52 +26,39 @@
|
||||||
|
|
||||||
<%def name="leading_buttons()">
|
<%def name="leading_buttons()">
|
||||||
% if master.has_worksheet and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
% if master.has_worksheet and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
||||||
% if use_buefy:
|
<once-button type="is-primary"
|
||||||
<once-button type="is-primary"
|
tag="a" href="${url('{}.worksheet'.format(route_prefix), uuid=batch.uuid)}"
|
||||||
tag="a" href="${url('{}.worksheet'.format(route_prefix), uuid=batch.uuid)}"
|
icon-left="edit"
|
||||||
icon-left="edit"
|
text="Edit as Worksheet">
|
||||||
text="Edit as Worksheet">
|
</once-button>
|
||||||
</once-button>
|
|
||||||
% else:
|
|
||||||
<button type="button" class="load-worksheet">Edit as Worksheet</button>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="refresh_button()">
|
<%def name="refresh_button()">
|
||||||
% if master.batch_refreshable(batch) and master.has_perm('refresh'):
|
% if master.batch_refreshable(batch) and master.has_perm('refresh'):
|
||||||
% if use_buefy:
|
## TODO: this should surely use a POST request?
|
||||||
## TODO: this should surely use a POST request?
|
<once-button type="is-primary"
|
||||||
<once-button type="is-primary"
|
tag="a" href="${url('{}.refresh'.format(route_prefix), uuid=batch.uuid)}"
|
||||||
tag="a" href="${url('{}.refresh'.format(route_prefix), uuid=batch.uuid)}"
|
text="Refresh Data"
|
||||||
text="Refresh Data"
|
icon-left="redo">
|
||||||
icon-left="redo">
|
</once-button>
|
||||||
</once-button>
|
|
||||||
% else:
|
|
||||||
<button type="button" class="button" id="refresh-data">Refresh Data</button>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="trailing_buttons()">
|
<%def name="trailing_buttons()">
|
||||||
% if master.has_worksheet_file and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
% if master.has_worksheet_file and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
||||||
% if use_buefy:
|
<b-button tag="a"
|
||||||
<b-button tag="a"
|
href="${master.get_action_url('download_worksheet', batch)}"
|
||||||
href="${master.get_action_url('download_worksheet', batch)}"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="fas fa-download">
|
||||||
icon-left="fas fa-download">
|
Download Worksheet
|
||||||
Download Worksheet
|
</b-button>
|
||||||
</b-button>
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="fas fa-upload"
|
||||||
icon-left="fas fa-upload"
|
@click="$emit('show-upload')">
|
||||||
@click="$emit('show-upload')">
|
Upload Worksheet
|
||||||
Upload Worksheet
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.link_to("Download Worksheet", master.get_action_url('download_worksheet', batch), class_='button')}
|
|
||||||
<button type="button" class="upload-worksheet">Upload Worksheet</button>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -154,34 +68,12 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_status_breakdown()">
|
<%def name="render_status_breakdown()">
|
||||||
% if use_buefy:
|
<div class="object-helper">
|
||||||
<div class="object-helper">
|
<h3>Row Status Breakdown</h3>
|
||||||
<h3>Row Status Breakdown</h3>
|
<div class="object-helper-content">
|
||||||
<div class="object-helper-content">
|
${status_breakdown_grid}
|
||||||
${status_breakdown_grid}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
% elif status_breakdown is not Undefined and status_breakdown is not None:
|
|
||||||
<div class="object-helper">
|
|
||||||
<h3>Row Status Breakdown</h3>
|
|
||||||
<div class="object-helper-content">
|
|
||||||
% if status_breakdown:
|
|
||||||
<div class="grid full">
|
|
||||||
<table>
|
|
||||||
% for i, (status, count) in enumerate(status_breakdown):
|
|
||||||
<tr class="${'even' if i % 2 == 0 else 'odd'}">
|
|
||||||
<td>${status}</td>
|
|
||||||
<td>${count}</td>
|
|
||||||
</tr>
|
|
||||||
% endfor
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
% else:
|
|
||||||
<p>Nothing to report yet.</p>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_execute_helper()">
|
<%def name="render_execute_helper()">
|
||||||
|
@ -197,22 +89,21 @@
|
||||||
% elif master.handler.executable(batch):
|
% elif master.handler.executable(batch):
|
||||||
% if master.has_perm('execute'):
|
% if master.has_perm('execute'):
|
||||||
<p>Batch has not yet been executed.</p>
|
<p>Batch has not yet been executed.</p>
|
||||||
% if use_buefy:
|
<br />
|
||||||
<br />
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
% if not execute_enabled:
|
||||||
% if not execute_enabled:
|
disabled
|
||||||
disabled
|
% if why_not_execute:
|
||||||
% if why_not_execute:
|
title="${why_not_execute}"
|
||||||
title="${why_not_execute}"
|
% endif
|
||||||
% endif
|
% endif
|
||||||
% endif
|
@click="showExecutionDialog = true"
|
||||||
@click="showExecutionDialog = true"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="arrow-circle-right">
|
||||||
icon-left="arrow-circle-right">
|
${execute_title}
|
||||||
${execute_title}
|
</b-button>
|
||||||
</b-button>
|
|
||||||
|
|
||||||
% if execute_enabled:
|
% if execute_enabled:
|
||||||
<b-modal has-modal-card
|
<b-modal has-modal-card
|
||||||
:active.sync="showExecutionDialog">
|
:active.sync="showExecutionDialog">
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
|
@ -245,22 +136,8 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
% endif
|
|
||||||
|
|
||||||
% else:
|
|
||||||
## no buefy, do legacy thing
|
|
||||||
<button type="button"
|
|
||||||
% if not execute_enabled:
|
|
||||||
disabled="disabled"
|
|
||||||
% endif
|
|
||||||
% if why_not_execute:
|
|
||||||
title="${why_not_execute}"
|
|
||||||
% endif
|
|
||||||
class="button is-primary"
|
|
||||||
id="execute-batch">
|
|
||||||
${execute_title}
|
|
||||||
</button>
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
% else:
|
% else:
|
||||||
<p>TODO: batch *may* be executed, but not by *you*</p>
|
<p>TODO: batch *may* be executed, but not by *you*</p>
|
||||||
% endif
|
% endif
|
||||||
|
@ -281,71 +158,51 @@
|
||||||
${parent.render_this_page()}
|
${parent.render_this_page()}
|
||||||
|
|
||||||
% if master.has_worksheet_file and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
% if master.has_worksheet_file and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
||||||
% if use_buefy:
|
<b-modal has-modal-card
|
||||||
<b-modal has-modal-card
|
:active.sync="showUploadDialog">
|
||||||
:active.sync="showUploadDialog">
|
<div class="modal-card">
|
||||||
<div class="modal-card">
|
|
||||||
|
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">Upload Worksheet</p>
|
<p class="modal-card-title">Upload Worksheet</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
<p>
|
|
||||||
This will <span class="has-text-weight-bold">update</span>
|
|
||||||
the batch data with the worksheet file you provide.
|
|
||||||
Please be certain to use the right one!
|
|
||||||
</p>
|
|
||||||
<br />
|
|
||||||
<${upload_worksheet_form.component} ref="uploadForm">
|
|
||||||
</${upload_worksheet_form.component}>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<footer class="modal-card-foot">
|
|
||||||
<b-button @click="showUploadDialog = false">
|
|
||||||
Cancel
|
|
||||||
</b-button>
|
|
||||||
<b-button type="is-primary"
|
|
||||||
@click="submitUpload()"
|
|
||||||
icon-pack="fas"
|
|
||||||
icon-left="fas fa-upload"
|
|
||||||
:disabled="uploadButtonDisabled">
|
|
||||||
{{ uploadButtonText }}
|
|
||||||
</b-button>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</b-modal>
|
|
||||||
% else:
|
|
||||||
<div id="upload-worksheet-dialog" style="display: none;">
|
|
||||||
<p>
|
<p>
|
||||||
This will <strong>update</strong> the batch data with the worksheet
|
This will <span class="has-text-weight-bold">update</span>
|
||||||
file you provide. Please be certain to use the right one!
|
the batch data with the worksheet file you provide.
|
||||||
|
Please be certain to use the right one!
|
||||||
</p>
|
</p>
|
||||||
${upload_worksheet_form.render_deform(buttons=False, form_kwargs={'name': 'upload-worksheet'})|n}
|
<br />
|
||||||
</div>
|
<${upload_worksheet_form.component} ref="uploadForm">
|
||||||
% endif
|
</${upload_worksheet_form.component}>
|
||||||
% endif
|
</section>
|
||||||
|
|
||||||
% if not use_buefy:
|
<footer class="modal-card-foot">
|
||||||
% if master.handler.executable(batch) and master.has_perm('execute'):
|
<b-button @click="showUploadDialog = false">
|
||||||
<div id="execution-options-dialog" style="display: none;">
|
Cancel
|
||||||
${execute_form.render_deform(form_kwargs={'name': 'batch-execution'}, buttons=False)|n}
|
</b-button>
|
||||||
</div>
|
<b-button type="is-primary"
|
||||||
% endif
|
@click="submitUpload()"
|
||||||
|
icon-pack="fas"
|
||||||
|
icon-left="fas fa-upload"
|
||||||
|
:disabled="uploadButtonDisabled">
|
||||||
|
{{ uploadButtonText }}
|
||||||
|
</b-button>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</b-modal>
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page_template()">
|
<%def name="render_this_page_template()">
|
||||||
${parent.render_this_page_template()}
|
${parent.render_this_page_template()}
|
||||||
% if use_buefy:
|
% if master.has_worksheet_file and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
||||||
% if master.has_worksheet_file and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
${upload_worksheet_form.render_deform(buttons=False, form_kwargs={'ref': 'actualUploadForm'})|n}
|
||||||
${upload_worksheet_form.render_deform(buttons=False, form_kwargs={'ref': 'actualUploadForm'})|n}
|
% endif
|
||||||
% endif
|
% if master.handler.executable(batch) and master.has_perm('execute'):
|
||||||
% if master.handler.executable(batch) and master.has_perm('execute'):
|
${execute_form.render_deform(form_kwargs={'ref': 'actualExecuteForm'}, buttons=False)|n}
|
||||||
${execute_form.render_deform(form_kwargs={'ref': 'actualExecuteForm'}, buttons=False)|n}
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -358,7 +215,7 @@
|
||||||
|
|
||||||
<%def name="render_row_grid_tools()">
|
<%def name="render_row_grid_tools()">
|
||||||
${parent.render_row_grid_tools()}
|
${parent.render_row_grid_tools()}
|
||||||
% if use_buefy and master.rows_bulk_deletable and not batch.executed and master.has_perm('delete_rows'):
|
% if master.rows_bulk_deletable and not batch.executed and master.has_perm('delete_rows'):
|
||||||
<b-button type="is-danger"
|
<b-button type="is-danger"
|
||||||
@click="deleteResultsInit()"
|
@click="deleteResultsInit()"
|
||||||
:disabled="!total"
|
:disabled="!total"
|
||||||
|
|
|
@ -1,26 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/page.mako" />
|
<%inherit file="/page.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('.worksheet .current-entry input').focus(function(event) {
|
|
||||||
$(this).parents('tr:first').addClass('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.worksheet .current-entry input').blur(function(event) {
|
|
||||||
$(this).parents('tr:first').removeClass('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
|
|
@ -4,22 +4,16 @@
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if use_buefy:
|
<style type="text/css">
|
||||||
<style type="text/css">
|
.this-page-content {
|
||||||
.this-page-content {
|
flex-grow: 1;
|
||||||
flex-grow: 1;
|
}
|
||||||
}
|
</style>
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
<br />
|
<br />
|
||||||
% if use_buefy:
|
<customer-order-creator></customer-order-creator>
|
||||||
<customer-order-creator></customer-order-creator>
|
|
||||||
% else:
|
|
||||||
<p>Sorry, but this page is not supported by your current theme configuration.</p>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="order_form_buttons()">
|
<%def name="order_form_buttons()">
|
||||||
|
|
|
@ -12,38 +12,22 @@
|
||||||
${parent.grid_tools()}
|
${parent.grid_tools()}
|
||||||
|
|
||||||
% if request.has_perm('datasync.restart'):
|
% if request.has_perm('datasync.restart'):
|
||||||
% if use_buefy:
|
|
||||||
${h.form(url('datasync.restart'), name='restart-datasync', class_='control', **{'@submit': 'submitRestartDatasyncForm'})}
|
${h.form(url('datasync.restart'), name='restart-datasync', class_='control', **{'@submit': 'submitRestartDatasyncForm'})}
|
||||||
% else:
|
|
||||||
${h.form(url('datasync.restart'), name='restart-datasync', class_='autodisable')}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
% if use_buefy:
|
|
||||||
<b-button native-type="submit"
|
<b-button native-type="submit"
|
||||||
:disabled="restartDatasyncFormSubmitting">
|
:disabled="restartDatasyncFormSubmitting">
|
||||||
{{ restartDatasyncFormButtonText }}
|
{{ restartDatasyncFormButtonText }}
|
||||||
</b-button>
|
</b-button>
|
||||||
% else:
|
|
||||||
${h.submit('submit', "Restart DataSync", data_working_label="Restarting DataSync", class_='button')}
|
|
||||||
% endif
|
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
% if allow_filemon_restart and request.has_perm('filemon.restart'):
|
% if allow_filemon_restart and request.has_perm('filemon.restart'):
|
||||||
% if use_buefy:
|
|
||||||
${h.form(url('filemon.restart'), name='restart-filemon', class_='control', **{'@submit': 'submitRestartFilemonForm'})}
|
${h.form(url('filemon.restart'), name='restart-filemon', class_='control', **{'@submit': 'submitRestartFilemonForm'})}
|
||||||
% else:
|
|
||||||
${h.form(url('filemon.restart'), name='restart-filemon', class_='autodisable')}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
% if use_buefy:
|
|
||||||
<b-button native-type="submit"
|
<b-button native-type="submit"
|
||||||
:disabled="restartFilemonFormSubmitting">
|
:disabled="restartFilemonFormSubmitting">
|
||||||
{{ restartFilemonFormButtonText }}
|
{{ restartFilemonFormButtonText }}
|
||||||
</b-button>
|
</b-button>
|
||||||
% else:
|
|
||||||
${h.submit('submit', "Restart FileMon", data_working_label="Restarting FileMon", class_='button')}
|
|
||||||
% endif
|
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
|
|
|
@ -3,109 +3,10 @@
|
||||||
oid oid|field.oid;
|
oid oid|field.oid;
|
||||||
field_display field_display;
|
field_display field_display;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;
|
||||||
url url|field.widget.service_url;
|
url url|field.widget.service_url;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy"
|
<div tal:define="vmodel vmodel|'field_model_' + name;"
|
||||||
id="${oid}-container"
|
|
||||||
class="autocomplete-container">
|
|
||||||
<input type="hidden"
|
|
||||||
name="${name}"
|
|
||||||
id="${oid}"
|
|
||||||
value="${cstruct}" />
|
|
||||||
|
|
||||||
<input type="text"
|
|
||||||
name="${oid}-textbox"
|
|
||||||
id="${oid}-textbox"
|
|
||||||
value="${field_display}"
|
|
||||||
class="autocomplete-textbox"
|
|
||||||
style="display: none;" />
|
|
||||||
|
|
||||||
<div id="${oid}-display"
|
|
||||||
class="autocomplete-display"
|
|
||||||
style="display: none;">
|
|
||||||
|
|
||||||
<span>${field_display or ''}</span>
|
|
||||||
<button type="button" id="${oid}-change" class="autocomplete-change">Change</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
|
|
||||||
$('#' + oid + '-textbox').autocomplete(${options});
|
|
||||||
|
|
||||||
$('#' + oid + '-textbox').on('autocompleteselect', function (event, ui) {
|
|
||||||
$('#' + oid).val(ui.item.value);
|
|
||||||
$('#' + oid + '-display span:first').text(ui.item.label);
|
|
||||||
$('#' + oid + '-textbox').hide();
|
|
||||||
$('#' + oid + '-display').show();
|
|
||||||
$('#' + oid + '-textbox').trigger('autocompletevalueselected',
|
|
||||||
[ui.item.value, ui.item.label]);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#' + oid + '-change').click(function() {
|
|
||||||
$('#' + oid).val('');
|
|
||||||
$('#' + oid + '-display').hide();
|
|
||||||
with ($('#' + oid + '-textbox')) {
|
|
||||||
val('');
|
|
||||||
show();
|
|
||||||
focus();
|
|
||||||
}
|
|
||||||
$('#' + oid + '-textbox').trigger('autocompletevaluecleared');
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script tal:condition="cleared_callback" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
$('#' + oid + '-textbox').on('autocompletevaluecleared', function() {
|
|
||||||
${cleared_callback}();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script tal:condition="selected_callback" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
$('#' + oid + '-textbox').on('autocompletevalueselected', function(event, uuid, label) {
|
|
||||||
${selected_callback}(uuid, label);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script tal:condition="cstruct" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
$('#' + oid + '-display').show();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script tal:condition="not cstruct" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
$('#' + oid + '-textbox').show();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
<tailbone-autocomplete name="${name}"
|
<tailbone-autocomplete name="${name}"
|
||||||
ref="${ref}"
|
ref="${ref}"
|
||||||
|
|
|
@ -2,38 +2,11 @@
|
||||||
<div tal:define="oid oid|field.oid;
|
<div tal:define="oid oid|field.oid;
|
||||||
name name|field.name;
|
name name|field.name;
|
||||||
css_class css_class|field.widget.css_class;
|
css_class css_class|field.widget.css_class;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
i18n:domain="deform"
|
i18n:domain="deform"
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + name;"
|
||||||
${field.start_mapping()}
|
|
||||||
<div>
|
|
||||||
<input type="text" name="cases" value="${cases}"
|
|
||||||
tal:attributes="style style;
|
|
||||||
class string: form-control ${css_class or ''};
|
|
||||||
cases_attributes|field.widget.cases_attributes|{};"
|
|
||||||
placeholder="cases"
|
|
||||||
autocomplete="off"
|
|
||||||
id="${oid}-cases"/>
|
|
||||||
Cases
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="text" name="units" value="${units}"
|
|
||||||
tal:attributes="class string: form-control ${css_class or ''};
|
|
||||||
style style;
|
|
||||||
units_attributes|field.widget.units_attributes|{};"
|
|
||||||
placeholder="units"
|
|
||||||
autocomplete="off"
|
|
||||||
id="${oid}-units"/>
|
|
||||||
Units
|
|
||||||
</div>
|
|
||||||
${field.end_mapping()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
${field.start_mapping()}
|
${field.start_mapping()}
|
||||||
|
|
|
@ -2,21 +2,10 @@
|
||||||
true_val true_val|field.widget.true_val;
|
true_val true_val|field.widget.true_val;
|
||||||
css_class css_class|field.widget.css_class;
|
css_class css_class|field.widget.css_class;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;
|
||||||
oid oid|field.oid;
|
oid oid|field.oid;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" class="checkbox">
|
<div tal:define="vmodel vmodel|'field_model_' + name;">
|
||||||
<input type="checkbox"
|
|
||||||
name="${name}" value="${true_val}"
|
|
||||||
id="${oid}"
|
|
||||||
tal:attributes="checked cstruct == true_val;
|
|
||||||
class css_class;
|
|
||||||
style style;" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;">
|
|
||||||
<b-checkbox name="${name}"
|
<b-checkbox name="${name}"
|
||||||
v-model="${vmodel}"
|
v-model="${vmodel}"
|
||||||
native-value="${true_val}">
|
native-value="${true_val}">
|
||||||
|
|
|
@ -2,37 +2,9 @@
|
||||||
tal:define="oid oid|field.oid;
|
tal:define="oid oid|field.oid;
|
||||||
name name|field.name;
|
name name|field.name;
|
||||||
css_class css_class|field.widget.css_class;
|
css_class css_class|field.widget.css_class;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;">
|
||||||
use_buefy use_buefy|0;">
|
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div>
|
||||||
${field.start_mapping()}
|
|
||||||
<div>
|
|
||||||
<input type="password"
|
|
||||||
name="${name}"
|
|
||||||
value="${field.widget.redisplay and cstruct or ''}"
|
|
||||||
tal:attributes="class string: form-control ${css_class or ''};
|
|
||||||
style style;
|
|
||||||
attributes|field.widget.attributes|{};"
|
|
||||||
id="${oid}"
|
|
||||||
i18n:attributes="placeholder"
|
|
||||||
placeholder="Password"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input type="password"
|
|
||||||
name="${name}-confirm"
|
|
||||||
value="${field.widget.redisplay and confirm or ''}"
|
|
||||||
tal:attributes="class string: form-control ${css_class or ''};
|
|
||||||
style style;
|
|
||||||
confirm_attributes|field.widget.confirm_attributes|{};"
|
|
||||||
id="${oid}-confirm"
|
|
||||||
i18n:attributes="placeholder"
|
|
||||||
placeholder="Confirm Password"/>
|
|
||||||
</div>
|
|
||||||
${field.end_mapping()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy">
|
|
||||||
${field.start_mapping()}
|
${field.start_mapping()}
|
||||||
<b-input type="password"
|
<b-input type="password"
|
||||||
name="${name}"
|
name="${name}"
|
||||||
|
|
|
@ -3,40 +3,10 @@
|
||||||
oid oid|field.oid;
|
oid oid|field.oid;
|
||||||
field_name field_name|field.name;
|
field_name field_name|field.name;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;
|
||||||
type_name type_name|field.widget.type_name;
|
type_name type_name|field.widget.type_name;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + field_name;">
|
||||||
${field.start_mapping()}
|
|
||||||
<input type="${type_name}"
|
|
||||||
name="date"
|
|
||||||
value="${cstruct}"
|
|
||||||
|
|
||||||
tal:attributes="class string: ${css_class or ''} form-control;
|
|
||||||
style style"
|
|
||||||
id="${oid}"/>
|
|
||||||
${field.end_mapping()}
|
|
||||||
<script type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function deform_cb(oid) {
|
|
||||||
$('#' + oid).datepicker(${options_json});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
<script tal:condition="selected_callback" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
$('#' + oid).datepicker('option', 'onSelect', ${selected_callback});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + field_name;">
|
|
||||||
${field.start_mapping()}
|
${field.start_mapping()}
|
||||||
<tailbone-datepicker name="date"
|
<tailbone-datepicker name="date"
|
||||||
id="${oid}"
|
id="${oid}"
|
||||||
|
|
|
@ -2,29 +2,9 @@
|
||||||
<tal:block tal:define="oid oid|field.oid;
|
<tal:block tal:define="oid oid|field.oid;
|
||||||
css_class css_class|field.widget.css_class;
|
css_class css_class|field.widget.css_class;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;
|
||||||
field_name field_name|field.name;
|
field_name field_name|field.name;">
|
||||||
use_buefy use_buefy|0;">
|
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + field_name;">
|
||||||
${field.start_mapping()}
|
|
||||||
<input type="file" name="upload" id="${oid}"
|
|
||||||
tal:attributes="style style;
|
|
||||||
accept accept|field.widget.accept;
|
|
||||||
data-filename cstruct.get('filename');
|
|
||||||
attributes|field.widget.attributes|{};"/>
|
|
||||||
<input tal:define="uid cstruct.get('uid')"
|
|
||||||
tal:condition="uid"
|
|
||||||
type="hidden" name="uid" value="${uid}"/>
|
|
||||||
${field.end_mapping()}
|
|
||||||
<script type="text/javascript">
|
|
||||||
deform.addCallback('${oid}', function (oid) {
|
|
||||||
$('#' + oid).upload();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + field_name;">
|
|
||||||
${field.start_mapping()}
|
${field.start_mapping()}
|
||||||
<b-field class="file">
|
<b-field class="file">
|
||||||
<b-upload name="upload"
|
<b-upload name="upload"
|
||||||
|
|
|
@ -3,21 +3,9 @@
|
||||||
oid oid|field.oid;
|
oid oid|field.oid;
|
||||||
mask mask|field.widget.mask;
|
mask mask|field.widget.mask;
|
||||||
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
|
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
<div tal:define="vmodel vmodel|'field_model_' + name;"
|
||||||
<input tal:condition="not use_buefy"
|
|
||||||
type="password"
|
|
||||||
name="${name}"
|
|
||||||
value="${field.widget.redisplay and cstruct or ''}"
|
|
||||||
tal:attributes="style style;
|
|
||||||
class string: form-control ${css_class or ''};
|
|
||||||
attributes|field.widget.attributes|{};"
|
|
||||||
id="${oid}" />
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
<b-input name="${name}"
|
<b-input name="${name}"
|
||||||
v-model="${vmodel}"
|
v-model="${vmodel}"
|
||||||
|
|
|
@ -8,26 +8,7 @@
|
||||||
autocomplete autocomplete|field.widget.autocomplete|'off';"
|
autocomplete autocomplete|field.widget.autocomplete|'off';"
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + field_name;">
|
||||||
<input type="text" name="${name}" value="${cstruct}"
|
|
||||||
tal:attributes="class string: form-control ${css_class or ''};
|
|
||||||
style style;
|
|
||||||
autocomplete autocomplete;
|
|
||||||
"
|
|
||||||
id="${oid}"/>
|
|
||||||
%
|
|
||||||
<script tal:condition="mask" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
$("#" + oid).mask("${mask}",
|
|
||||||
{placeholder:"${mask_placeholder}"});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + field_name;">
|
|
||||||
<!-- TODO: need to handle mask somehow? -->
|
<!-- TODO: need to handle mask somehow? -->
|
||||||
<b-input name="${field_name}"
|
<b-input name="${field_name}"
|
||||||
id="${oid}"
|
id="${oid}"
|
||||||
|
|
|
@ -1,41 +1,8 @@
|
||||||
<div tal:define="oid oid|field.oid;
|
<div tal:define="oid oid|field.oid;
|
||||||
true_val true_val|field.widget.true_val;
|
true_val true_val|field.widget.true_val;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy"
|
<div>
|
||||||
tal:omit-tag="">
|
|
||||||
${field.start_mapping()}
|
|
||||||
|
|
||||||
<div class="permissions-outer">
|
|
||||||
|
|
||||||
<tal:loop tal:repeat="groupkey sorted(permissions, key=lambda k: permissions[k]['label'].lower())">
|
|
||||||
<div tal:define="perms permissions[groupkey]['perms'];"
|
|
||||||
class="permissions-group">
|
|
||||||
<p class="group-label">${permissions[groupkey]['label']}</p>
|
|
||||||
|
|
||||||
<tal:loop tal:repeat="key sorted(perms, key=lambda p: perms[p]['label'].lower())">
|
|
||||||
<div class="perm">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox"
|
|
||||||
name="${key}"
|
|
||||||
id="${oid}-${key}"
|
|
||||||
value="${true_val}"
|
|
||||||
tal:attributes="checked python:field.widget.get_checked_value(cstruct, key);" />
|
|
||||||
${perms[key]['label']}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</tal:loop>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</tal:loop>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${field.end_mapping()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy">
|
|
||||||
${field.start_mapping()}
|
${field.start_mapping()}
|
||||||
|
|
||||||
<div class="level">
|
<div class="level">
|
||||||
|
|
|
@ -7,58 +7,10 @@
|
||||||
unicode unicode|str;
|
unicode unicode|str;
|
||||||
optgroup_class optgroup_class|field.widget.optgroup_class;
|
optgroup_class optgroup_class|field.widget.optgroup_class;
|
||||||
multiple multiple|field.widget.multiple;
|
multiple multiple|field.widget.multiple;
|
||||||
use_buefy use_buefy|0;
|
|
||||||
input_handler input_handler|'';"
|
input_handler input_handler|'';"
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + name;">
|
||||||
<input type="hidden" name="__start__" value="${name}:sequence"
|
|
||||||
tal:condition="multiple" />
|
|
||||||
<div class="select">
|
|
||||||
<select tal:attributes="
|
|
||||||
name name;
|
|
||||||
id oid;
|
|
||||||
class string: form-control ${css_class or ''};
|
|
||||||
multiple multiple;
|
|
||||||
size size;
|
|
||||||
style style;">
|
|
||||||
<tal:loop tal:repeat="item values">
|
|
||||||
<optgroup tal:condition="isinstance(item, optgroup_class)"
|
|
||||||
tal:attributes="label item.label">
|
|
||||||
<option tal:repeat="(value, description) item.options"
|
|
||||||
tal:attributes="
|
|
||||||
selected python:field.widget.get_select_value(cstruct, value);
|
|
||||||
class css_class;
|
|
||||||
label field.widget.long_label_generator and description;
|
|
||||||
value value"
|
|
||||||
tal:content="field.widget.long_label_generator and field.widget.long_label_generator(item.label, description) or description"/>
|
|
||||||
</optgroup>
|
|
||||||
<option tal:condition="not isinstance(item, optgroup_class)"
|
|
||||||
tal:attributes="
|
|
||||||
selected python:field.widget.get_select_value(cstruct, item[0]);
|
|
||||||
class css_class;
|
|
||||||
value item[0]">${item[1]}</option>
|
|
||||||
</tal:loop>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<input type="hidden" name="__end__" value="${name}:sequence"
|
|
||||||
tal:condition="multiple" />
|
|
||||||
<script tal:condition="not multiple" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function(oid) {
|
|
||||||
$('#' + oid).selectmenu();
|
|
||||||
$('#' + oid).on('selectmenuopen', function(event, ui) {
|
|
||||||
show_all_options($(this));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;"
|
|
||||||
>
|
|
||||||
<input type="hidden" name="__start__" value="${name}:sequence"
|
<input type="hidden" name="__start__" value="${name}:sequence"
|
||||||
tal:condition="multiple" />
|
tal:condition="multiple" />
|
||||||
<b-select tal:attributes="name name;
|
<b-select tal:attributes="name name;
|
||||||
|
|
|
@ -3,22 +3,10 @@
|
||||||
css_class css_class|field.widget.css_class;
|
css_class css_class|field.widget.css_class;
|
||||||
oid oid|field.oid;
|
oid oid|field.oid;
|
||||||
name name|field.name;
|
name name|field.name;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + name;">
|
||||||
<textarea tal:attributes="rows rows;
|
|
||||||
cols cols;
|
|
||||||
class string: form-control ${css_class or ''};
|
|
||||||
style style;
|
|
||||||
attributes|field.widget.attributes|{};"
|
|
||||||
id="${oid}"
|
|
||||||
name="${name}">${cstruct}</textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;">
|
|
||||||
<b-input type="textarea"
|
<b-input type="textarea"
|
||||||
name="${name}"
|
name="${name}"
|
||||||
v-model="${vmodel}">
|
v-model="${vmodel}">
|
||||||
|
|
|
@ -4,29 +4,10 @@
|
||||||
mask mask|field.widget.mask;
|
mask mask|field.widget.mask;
|
||||||
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
|
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
|
||||||
style style|field.widget.style;
|
style style|field.widget.style;
|
||||||
use_buefy use_buefy|0;
|
|
||||||
placeholder placeholder|getattr(field.widget, 'placeholder', '');
|
placeholder placeholder|getattr(field.widget, 'placeholder', '');
|
||||||
autocomplete autocomplete|getattr(field.widget, 'autocomplete', 'on');"
|
autocomplete autocomplete|getattr(field.widget, 'autocomplete', 'on');"
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + name;"
|
||||||
<input type="text" name="${name}" value="${cstruct}"
|
|
||||||
tal:attributes="class string: form-control ${css_class or ''};
|
|
||||||
style style;
|
|
||||||
attributes|field.widget.attributes|{};"
|
|
||||||
autocomplete="${autocomplete}"
|
|
||||||
id="${oid}"/>
|
|
||||||
<script tal:condition="mask" type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function (oid) {
|
|
||||||
$("#" + oid).mask("${mask}",
|
|
||||||
{placeholder:"${mask_placeholder}"});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
<b-input tal:attributes="name name;
|
<b-input tal:attributes="name name;
|
||||||
v-model vmodel;
|
v-model vmodel;
|
||||||
|
|
|
@ -4,32 +4,10 @@
|
||||||
oid oid|field.oid;
|
oid oid|field.oid;
|
||||||
style style|field.widget.style|None;
|
style style|field.widget.style|None;
|
||||||
type_name type_name|field.widget.type_name;
|
type_name type_name|field.widget.type_name;
|
||||||
field_name field_name|field.name;
|
field_name field_name|field.name;"
|
||||||
use_buefy use_buefy|0;"
|
|
||||||
tal:omit-tag="">
|
tal:omit-tag="">
|
||||||
|
|
||||||
<div tal:condition="not use_buefy" tal:omit-tag="">
|
<div tal:define="vmodel vmodel|'field_model_' + field_name;">
|
||||||
${field.start_mapping()}
|
|
||||||
<input type="${type_name}"
|
|
||||||
name="time"
|
|
||||||
value="${cstruct}"
|
|
||||||
tal:attributes="size size;
|
|
||||||
class string: ${css_class or ''} form-control;
|
|
||||||
style style"
|
|
||||||
id="${oid}"/>
|
|
||||||
${field.end_mapping()}
|
|
||||||
<script type="text/javascript">
|
|
||||||
deform.addCallback(
|
|
||||||
'${oid}',
|
|
||||||
function(oid) {
|
|
||||||
$('#' + oid).timepicker(${options_json});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
|
||||||
tal:define="vmodel vmodel|'field_model_' + field_name;">
|
|
||||||
${field.start_mapping()}
|
${field.start_mapping()}
|
||||||
<tailbone-timepicker name="time"
|
<tailbone-timepicker name="time"
|
||||||
id="${oid}"
|
id="${oid}"
|
||||||
|
|
|
@ -1,20 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="page_content()">
|
|
||||||
${parent.page_content()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<h2>Employees</h2>
|
|
||||||
|
|
||||||
% if employees:
|
|
||||||
<p>The following employees are assigned to this department:</p>
|
|
||||||
${employees.render_grid()|n}
|
|
||||||
% else:
|
|
||||||
<p>No employees are assigned to this department.</p>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
${parent.modify_this_page_vars()}
|
${parent.modify_this_page_vars()}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
@ -3,36 +3,8 @@
|
||||||
|
|
||||||
## TODO: this page still uses jQuery but should use Vue.js
|
## TODO: this page still uses jQuery but should use Vue.js
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function autosize_message(scrolldown) {
|
|
||||||
var msg = $('#message');
|
|
||||||
var height = $(window).height() - msg.offset().top - 50;
|
|
||||||
msg.height(height);
|
|
||||||
if (scrolldown) {
|
|
||||||
msg.animate({scrollTop: msg.get(0).scrollHeight - height}, 250);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
autosize_message(true);
|
|
||||||
$('#message').focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
$(window).resize(function() {
|
|
||||||
autosize_message(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if use_buefy:
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.email-message-body {
|
.email-message-body {
|
||||||
border: 1px solid #000000;
|
border: 1px solid #000000;
|
||||||
|
@ -40,81 +12,48 @@
|
||||||
height: 500px;
|
height: 500px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
% else:
|
|
||||||
<style type="text/css">
|
|
||||||
#message {
|
|
||||||
border: 1px solid #000000;
|
|
||||||
height: 400px;
|
|
||||||
overflow: auto;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="object_helpers()">
|
<%def name="object_helpers()">
|
||||||
${parent.object_helpers()}
|
${parent.object_helpers()}
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Processing</p>
|
||||||
<p class="panel-heading">Processing</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
<div class="display: flex; flex-align: column;">
|
||||||
<div class="display: flex; flex-align: column;">
|
% if bounce.processed:
|
||||||
% if bounce.processed:
|
<p class="block">
|
||||||
<p class="block">
|
This bounce was processed
|
||||||
This bounce was processed
|
${h.pretty_datetime(request.rattail_config, bounce.processed)}
|
||||||
${h.pretty_datetime(request.rattail_config, bounce.processed)}
|
by ${bounce.processed_by}
|
||||||
by ${bounce.processed_by}
|
</p>
|
||||||
</p>
|
% if master.has_perm('unprocess'):
|
||||||
% if master.has_perm('unprocess'):
|
<once-button type="is-warning"
|
||||||
<once-button type="is-warning"
|
tag="a" href="${url('emailbounces.unprocess', uuid=bounce.uuid)}"
|
||||||
tag="a" href="${url('emailbounces.unprocess', uuid=bounce.uuid)}"
|
text="Mark this bounce as UN-processed">
|
||||||
text="Mark this bounce as UN-processed">
|
</once-button>
|
||||||
</once-button>
|
|
||||||
% endif
|
|
||||||
% else:
|
|
||||||
<p class="block">
|
|
||||||
This bounce has NOT yet been processed.
|
|
||||||
</p>
|
|
||||||
% if master.has_perm('process'):
|
|
||||||
<once-button type="is-primary"
|
|
||||||
tag="a" href="${url('emailbounces.process', uuid=bounce.uuid)}"
|
|
||||||
text="Mark this bounce as Processed">
|
|
||||||
</once-button>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</div>
|
% else:
|
||||||
</div>
|
<p class="block">
|
||||||
</nav>
|
This bounce has NOT yet been processed.
|
||||||
% endif
|
</p>
|
||||||
</%def>
|
% if master.has_perm('process'):
|
||||||
|
<once-button type="is-primary"
|
||||||
<%def name="context_menu_items()">
|
tag="a" href="${url('emailbounces.process', uuid=bounce.uuid)}"
|
||||||
${parent.context_menu_items()}
|
text="Mark this bounce as Processed">
|
||||||
% if not use_buefy:
|
</once-button>
|
||||||
% if not bounce.processed and request.has_perm('emailbounces.process'):
|
% endif
|
||||||
<li>${h.link_to("Mark this Email Bounce as Processed", url('emailbounces.process', uuid=bounce.uuid))}</li>
|
% endif
|
||||||
% elif bounce.processed and request.has_perm('emailbounces.unprocess'):
|
</div>
|
||||||
<li>${h.link_to("Mark this Email Bounce as UN-processed", url('emailbounces.unprocess', uuid=bounce.uuid))}</li>
|
</div>
|
||||||
% endif
|
</nav>
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="page_content()">
|
|
||||||
${parent.page_content()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<pre id="message">
|
|
||||||
${message}
|
|
||||||
</pre>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page()">
|
<%def name="render_this_page()">
|
||||||
${parent.render_this_page()}
|
${parent.render_this_page()}
|
||||||
% if use_buefy:
|
<pre class="email-message-body">
|
||||||
<pre class="email-message-body">
|
${message}
|
||||||
${message}
|
</pre>
|
||||||
</pre>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -22,12 +22,8 @@
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
<div class="form-wrapper">
|
<div class="form-wrapper">
|
||||||
% if use_buefy:
|
<br />
|
||||||
<br />
|
${self.render_buefy_form()}
|
||||||
${self.render_buefy_form()}
|
|
||||||
% else:
|
|
||||||
${self.render_form()}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,2 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
% if form.use_buefy:
|
${form.render_deform(buttons=buttons)|n}
|
||||||
${form.render_deform(buttons=buttons)|n}
|
|
||||||
% else:
|
|
||||||
<div class="form">
|
|
||||||
${form.render_deform(buttons=buttons)|n}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
|
@ -4,36 +4,27 @@
|
||||||
|
|
||||||
<%def name="title()">Login</%def>
|
<%def name="title()">Login</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/login.js'))}
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if use_buefy:
|
<style type="text/css">
|
||||||
<style type="text/css">
|
.logo img {
|
||||||
.logo img {
|
display: block;
|
||||||
display: block;
|
margin: 3rem auto;
|
||||||
margin: 3rem auto;
|
max-height: 350px;
|
||||||
max-height: 350px;
|
max-width: 800px;
|
||||||
max-width: 800px;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* must force a particular label with, in order to make sure */
|
/* must force a particular label with, in order to make sure */
|
||||||
/* the username and password inputs are the same size */
|
/* the username and password inputs are the same size */
|
||||||
.field.is-horizontal .field-label .label {
|
.field.is-horizontal .field-label .label {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 6rem;
|
width: 6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
justify-content: right;
|
justify-content: right;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
% else:
|
|
||||||
${h.stylesheet_link(request.static_url('tailbone:static/css/login.css'))}
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="logo()">
|
<%def name="logo()">
|
||||||
|
@ -55,21 +46,15 @@
|
||||||
${self.logo()}
|
${self.logo()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
% if use_buefy:
|
<div class="columns is-centered">
|
||||||
|
<div class="column is-narrow">
|
||||||
<div class="columns is-centered">
|
<div class="card">
|
||||||
<div class="column is-narrow">
|
<div class="card-content">
|
||||||
<div class="card">
|
<tailbone-form></tailbone-form>
|
||||||
<div class="card-content">
|
|
||||||
<tailbone-form></tailbone-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
% else:
|
</div>
|
||||||
${self.login_form()}
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,49 +5,31 @@
|
||||||
|
|
||||||
<%def name="render_buefy_form()">
|
<%def name="render_buefy_form()">
|
||||||
<br />
|
<br />
|
||||||
% if use_buefy:
|
<b-notification :closable="false">
|
||||||
<b-notification :closable="false">
|
You are about to clone the following ${model_title} as a new record:
|
||||||
You are about to clone the following ${model_title} as a new record:
|
</b-notification>
|
||||||
</b-notification>
|
|
||||||
% else:
|
|
||||||
<p>You are about to clone the following ${model_title} as a new record:</p>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
${parent.render_buefy_form()}
|
${parent.render_buefy_form()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form_buttons()">
|
<%def name="render_form_buttons()">
|
||||||
<br />
|
<br />
|
||||||
% if use_buefy:
|
<b-notification :closable="false">
|
||||||
<b-notification :closable="false">
|
Are you sure about this?
|
||||||
Are you sure about this?
|
</b-notification>
|
||||||
</b-notification>
|
|
||||||
% else:
|
|
||||||
<p>Are you sure about this?</p>
|
|
||||||
% endif
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
% if use_buefy:
|
|
||||||
${h.form(request.current_route_url(), **{'@submit': 'submitForm'})}
|
${h.form(request.current_route_url(), **{'@submit': 'submitForm'})}
|
||||||
% else:
|
|
||||||
${h.form(request.current_route_url(), class_='autodisable')}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
${h.hidden('clone', value='clone')}
|
${h.hidden('clone', value='clone')}
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
% if use_buefy:
|
<once-button tag="a" href="${form.cancel_url}"
|
||||||
<once-button tag="a" href="${form.cancel_url}"
|
text="Whoops, nevermind...">
|
||||||
text="Whoops, nevermind...">
|
</once-button>
|
||||||
</once-button>
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
native-type="submit"
|
||||||
native-type="submit"
|
:disabled="formSubmitting">
|
||||||
:disabled="formSubmitting">
|
{{ submitButtonText }}
|
||||||
{{ submitButtonText }}
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.link_to("Whoops, nevermind...", form.cancel_url, class_='button autodisable')}
|
|
||||||
${h.submit('submit', "Yes, please clone away")}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
|
@ -3,66 +3,32 @@
|
||||||
|
|
||||||
<%def name="title()">Delete ${model_title}: ${instance_title}</%def>
|
<%def name="title()">Delete ${model_title}: ${instance_title}</%def>
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
|
||||||
% if not use_buefy and master.viewable and master.has_perm('view'):
|
|
||||||
<li>${h.link_to("View this {}".format(model_title), action_url('view', instance))}</li>
|
|
||||||
% endif
|
|
||||||
% if not use_buefy and master.editable and master.has_perm('edit'):
|
|
||||||
<li>${h.link_to("Edit this {}".format(model_title), action_url('edit', instance))}</li>
|
|
||||||
% endif
|
|
||||||
% if not use_buefy and master.creatable and master.show_create_link and master.has_perm('create'):
|
|
||||||
% if master.creates_multiple:
|
|
||||||
<li>${h.link_to("Create new {}".format(model_title_plural), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% else:
|
|
||||||
<li>${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="render_buefy_form()">
|
<%def name="render_buefy_form()">
|
||||||
<br />
|
<br />
|
||||||
% if use_buefy:
|
<b-notification type="is-danger" :closable="false">
|
||||||
<b-notification type="is-danger" :closable="false">
|
You are about to delete the following ${model_title} and all associated data:
|
||||||
You are about to delete the following ${model_title} and all associated data:
|
</b-notification>
|
||||||
</b-notification>
|
|
||||||
% else:
|
|
||||||
<p>You are about to delete the following ${model_title} and all associated data:</p>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
${parent.render_buefy_form()}
|
${parent.render_buefy_form()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form_buttons()">
|
<%def name="render_form_buttons()">
|
||||||
<br />
|
<br />
|
||||||
% if use_buefy:
|
<b-notification type="is-danger" :closable="false">
|
||||||
<b-notification type="is-danger" :closable="false">
|
Are you sure about this?
|
||||||
Are you sure about this?
|
</b-notification>
|
||||||
</b-notification>
|
|
||||||
% else:
|
|
||||||
<p>Are you sure about this?</p>
|
|
||||||
% endif
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
% if use_buefy:
|
|
||||||
${h.form(request.current_route_url(), **{'@submit': 'submitForm'})}
|
${h.form(request.current_route_url(), **{'@submit': 'submitForm'})}
|
||||||
% else:
|
|
||||||
${h.form(request.current_route_url(), class_='autodisable')}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
% if use_buefy:
|
<once-button tag="a" href="${form.cancel_url}"
|
||||||
<once-button tag="a" href="${form.cancel_url}"
|
text="Whoops, nevermind...">
|
||||||
text="Whoops, nevermind...">
|
</once-button>
|
||||||
</once-button>
|
<b-button type="is-primary is-danger"
|
||||||
<b-button type="is-primary is-danger"
|
native-type="submit"
|
||||||
native-type="submit"
|
:disabled="formSubmitting">
|
||||||
:disabled="formSubmitting">
|
{{ formButtonText }}
|
||||||
{{ formButtonText }}
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
<a class="button" href="${form.cancel_url}">Whoops, nevermind...</a>
|
|
||||||
${h.submit('submit', "Yes, please DELETE this data forever!", class_='button is-primary')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
|
@ -3,38 +3,5 @@
|
||||||
|
|
||||||
<%def name="title()">Edit: ${instance_title}</%def>
|
<%def name="title()">Edit: ${instance_title}</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('form').submit(function() {
|
|
||||||
var submit = $(this).find('input[type="submit"]');
|
|
||||||
if (submit.length) {
|
|
||||||
submit.button('disable').button('option', 'label', "Saving, please wait...");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
|
||||||
% if not use_buefy and master.viewable and master.has_perm('view'):
|
|
||||||
<li>${h.link_to("View this {}".format(model_title), action_url('view', instance))}</li>
|
|
||||||
% endif
|
|
||||||
${self.context_menu_item_delete()}
|
|
||||||
% if not use_buefy and master.creatable and master.show_create_link and master.has_perm('create'):
|
|
||||||
% if master.creates_multiple:
|
|
||||||
<li>${h.link_to("Create new {}".format(model_title_plural), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% else:
|
|
||||||
<li>${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -1,31 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/form.mako" />
|
<%inherit file="/form.mako" />
|
||||||
|
|
||||||
<%def name="context_menu_item_delete()">
|
|
||||||
% if not use_buefy and master.deletable and instance_deletable and master.has_perm('delete'):
|
|
||||||
% if master.delete_confirm == 'simple':
|
|
||||||
<li>
|
|
||||||
## note, the `ref` here is for buefy only
|
|
||||||
${h.form(action_url('delete', instance), ref='deleteObjectForm')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
<a href="${action_url('delete', instance)}"
|
|
||||||
% if use_buefy:
|
|
||||||
@click.prevent="deleteObject"
|
|
||||||
% else:
|
|
||||||
class="delete-instance"
|
|
||||||
% endif
|
|
||||||
>
|
|
||||||
Delete this ${model_title}
|
|
||||||
</a>
|
|
||||||
${h.end_form()}
|
|
||||||
</li>
|
|
||||||
% else:
|
|
||||||
## assuming here that: delete_confirm == 'full'
|
|
||||||
<li>${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}</li>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
${parent.modify_this_page_vars()}
|
${parent.modify_this_page_vars()}
|
||||||
% if master.deletable and instance_deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
|
% if master.deletable and instance_deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
|
||||||
|
|
|
@ -12,142 +12,6 @@
|
||||||
|
|
||||||
<%def name="content_title()"></%def>
|
<%def name="content_title()"></%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
% if download_results_rows_path:
|
|
||||||
function downloadResultsRowsRedirect() {
|
|
||||||
location.href = '${url('{}.download_results_rows'.format(route_prefix))}?filename=${h.os.path.basename(download_results_rows_path)}';
|
|
||||||
}
|
|
||||||
// we give this 1 second before attempting the redirect; so this
|
|
||||||
// way the page should fully render before redirecting
|
|
||||||
window.setTimeout(downloadResultsRowsRedirect, 1000);
|
|
||||||
% endif
|
|
||||||
|
|
||||||
$('.grid-wrapper').gridwrapper();
|
|
||||||
|
|
||||||
% if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('click', '.grid .actions a.delete', function() {
|
|
||||||
if (confirm("Are you sure you wish to delete this ${model_title}?")) {
|
|
||||||
var link = $(this).get(0);
|
|
||||||
var form = $('#delete-object-form').get(0);
|
|
||||||
form.action = link.href;
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if master.mergeable and master.has_perm('merge'):
|
|
||||||
|
|
||||||
$('form[name="merge-things"] button').button('option', 'disabled', $('.grid').gridcore('count_selected') != 2);
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('gridchecked', '.grid', function(event, count) {
|
|
||||||
$('form[name="merge-things"] button').button('option', 'disabled', count != 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('form[name="merge-things"]').submit(function() {
|
|
||||||
var uuids = $('.grid').gridcore('selected_uuids');
|
|
||||||
if (uuids.length != 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$(this).find('[name="uuids"]').val(uuids.toString());
|
|
||||||
$(this).find('button')
|
|
||||||
.button('option', 'label', "Preparing to Merge...")
|
|
||||||
.button('disable');
|
|
||||||
});
|
|
||||||
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if master.has_rows and master.results_rows_downloadable:
|
|
||||||
|
|
||||||
$('#download-row-results-button').click(function() {
|
|
||||||
if (confirm("This will generate an Excel file which contains "
|
|
||||||
+ "not the results themselves, but the *rows* for "
|
|
||||||
+ "each.\n\nAre you sure you want this?")) {
|
|
||||||
disable_button(this);
|
|
||||||
var form = $(this).parents('form');
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)):
|
|
||||||
|
|
||||||
$('form[name="bulk-delete"] button').click(function() {
|
|
||||||
var count = $('.grid-wrapper').gridwrapper('results_count', true);
|
|
||||||
if (count === null) {
|
|
||||||
alert("There don't seem to be any results to delete!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (! confirm("You are about to delete " + count + " ${model_title_plural}.\n\nAre you sure?")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
$(this).button('disable').button('option', 'label', "Deleting Results...");
|
|
||||||
$('form[name="bulk-delete"]').submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if master.supports_set_enabled_toggle and request.has_perm('{}.enable_disable_set'.format(permission_prefix)):
|
|
||||||
$('form[name="enable-set"] button').click(function() {
|
|
||||||
var form = $(this).parents('form');
|
|
||||||
var uuids = $('.grid').gridcore('selected_uuids');
|
|
||||||
if (! uuids.length) {
|
|
||||||
alert("You must first select one or more objects to enable.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (! confirm("Are you sure you wish to ENABLE the " + uuids.length + " selected objects?")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
form.find('[name="uuids"]').val(uuids.toString());
|
|
||||||
disable_button(this);
|
|
||||||
form.submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('form[name="disable-set"] button').click(function() {
|
|
||||||
var form = $(this).parents('form');
|
|
||||||
var uuids = $('.grid').gridcore('selected_uuids');
|
|
||||||
if (! uuids.length) {
|
|
||||||
alert("You must first select one or more objects to disable.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (! confirm("Are you sure you wish to DISABLE the " + uuids.length + " selected objects?")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
form.find('[name="uuids"]').val(uuids.toString());
|
|
||||||
disable_button(this);
|
|
||||||
form.submit();
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if master.set_deletable and request.has_perm('{}.delete_set'.format(permission_prefix)):
|
|
||||||
$('form[name="delete-set"] button').click(function() {
|
|
||||||
var form = $(this).parents('form');
|
|
||||||
var uuids = $('.grid').gridcore('selected_uuids');
|
|
||||||
if (! uuids.length) {
|
|
||||||
alert("You must first select one or more objects to delete.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (! confirm("Are you sure you wish to DELETE the " + uuids.length + " selected objects?")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
form.find('[name="uuids"]').val(uuids.toString());
|
|
||||||
disable_button(this);
|
|
||||||
form.submit();
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
% if master.results_downloadable_csv and request.has_perm('{}.results_csv'.format(permission_prefix)):
|
% if master.results_downloadable_csv and request.has_perm('{}.results_csv'.format(permission_prefix)):
|
||||||
<li>${h.link_to("Download results as CSV", url('{}.results_csv'.format(route_prefix)))}</li>
|
<li>${h.link_to("Download results as CSV", url('{}.results_csv'.format(route_prefix)))}</li>
|
||||||
|
@ -155,13 +19,6 @@
|
||||||
% if master.results_downloadable_xlsx and request.has_perm('{}.results_xlsx'.format(permission_prefix)):
|
% if master.results_downloadable_xlsx and request.has_perm('{}.results_xlsx'.format(permission_prefix)):
|
||||||
<li>${h.link_to("Download results as XLSX", url('{}.results_xlsx'.format(route_prefix)))}</li>
|
<li>${h.link_to("Download results as XLSX", url('{}.results_xlsx'.format(route_prefix)))}</li>
|
||||||
% endif
|
% endif
|
||||||
% if not use_buefy and master.creatable and master.show_create_link and master.has_perm('create'):
|
|
||||||
% if master.creates_multiple:
|
|
||||||
<li>${h.link_to("Create new {}".format(model_title_plural), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% else:
|
|
||||||
<li>${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
% if master.has_input_file_templates and master.has_perm('create'):
|
% if master.has_input_file_templates and master.has_perm('create'):
|
||||||
% for template in six.itervalues(input_file_templates):
|
% for template in six.itervalues(input_file_templates):
|
||||||
<li>${h.link_to("Download {} Template".format(template['label']), template['effective_url'])}</li>
|
<li>${h.link_to("Download {} Template".format(template['label']), template['effective_url'])}</li>
|
||||||
|
@ -173,284 +30,233 @@
|
||||||
|
|
||||||
## download search results
|
## download search results
|
||||||
% if master.results_downloadable and master.has_perm('download_results'):
|
% if master.results_downloadable and master.has_perm('download_results'):
|
||||||
% if use_buefy:
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="fas fa-download"
|
||||||
icon-left="fas fa-download"
|
@click="showDownloadResultsDialog = true"
|
||||||
@click="showDownloadResultsDialog = true"
|
:disabled="!total">
|
||||||
:disabled="!total">
|
Download Results
|
||||||
Download Results
|
</b-button>
|
||||||
</b-button>
|
|
||||||
|
|
||||||
${h.form(url('{}.download_results'.format(route_prefix)), ref='download_results_form')}
|
${h.form(url('{}.download_results'.format(route_prefix)), ref='download_results_form')}
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
<input type="hidden" name="fmt" :value="downloadResultsFormat" />
|
<input type="hidden" name="fmt" :value="downloadResultsFormat" />
|
||||||
<input type="hidden" name="fields" :value="downloadResultsFieldsIncluded" />
|
<input type="hidden" name="fields" :value="downloadResultsFieldsIncluded" />
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
|
|
||||||
<b-modal :active.sync="showDownloadResultsDialog">
|
<b-modal :active.sync="showDownloadResultsDialog">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<p>
|
<p>
|
||||||
There are
|
There are
|
||||||
<span class="is-size-4 has-text-weight-bold">
|
<span class="is-size-4 has-text-weight-bold">
|
||||||
{{ total.toLocaleString('en') }} ${model_title_plural}
|
{{ total.toLocaleString('en') }} ${model_title_plural}
|
||||||
</span>
|
</span>
|
||||||
matching your current filters.
|
matching your current filters.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
You may download this set as a single data file if you like.
|
You may download this set as a single data file if you like.
|
||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<b-notification type="is-warning" :closable="false"
|
<b-notification type="is-warning" :closable="false"
|
||||||
v-if="downloadResultsFormat == 'xlsx' && total >= 1000">
|
v-if="downloadResultsFormat == 'xlsx' && total >= 1000">
|
||||||
Excel downloads for large data sets can take a long time to
|
Excel downloads for large data sets can take a long time to
|
||||||
generate, and bog down the server in the meantime. You are
|
generate, and bog down the server in the meantime. You are
|
||||||
encouraged to choose CSV for a large data set, even though
|
encouraged to choose CSV for a large data set, even though
|
||||||
the end result (file size) may be larger with CSV.
|
the end result (file size) may be larger with CSV.
|
||||||
</b-notification>
|
</b-notification>
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between">
|
<div style="display: flex; justify-content: space-between">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<b-field horizontal label="Format">
|
<b-field horizontal label="Format">
|
||||||
<b-select v-model="downloadResultsFormat">
|
<b-select v-model="downloadResultsFormat">
|
||||||
% for key, label in six.iteritems(master.download_results_supported_formats()):
|
% for key, label in six.iteritems(master.download_results_supported_formats()):
|
||||||
<option value="${key}">${label}</option>
|
<option value="${key}">${label}</option>
|
||||||
% endfor
|
% endfor
|
||||||
</b-select>
|
</b-select>
|
||||||
</b-field>
|
</b-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<div v-show="downloadResultsFieldsMode != 'choose'"
|
<div v-show="downloadResultsFieldsMode != 'choose'"
|
||||||
class="has-text-right">
|
class="has-text-right">
|
||||||
<p v-if="downloadResultsFieldsMode == 'default'">
|
<p v-if="downloadResultsFieldsMode == 'default'">
|
||||||
Will use DEFAULT fields.
|
Will use DEFAULT fields.
|
||||||
</p>
|
</p>
|
||||||
<p v-if="downloadResultsFieldsMode == 'all'">
|
<p v-if="downloadResultsFieldsMode == 'all'">
|
||||||
Will use ALL fields.
|
Will use ALL fields.
|
||||||
</p>
|
</p>
|
||||||
|
<br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="buttons is-right">
|
||||||
|
<b-button type="is-primary"
|
||||||
|
v-show="downloadResultsFieldsMode != 'default'"
|
||||||
|
@click="downloadResultsUseDefaultFields()">
|
||||||
|
Use Default Fields
|
||||||
|
</b-button>
|
||||||
|
<b-button type="is-primary"
|
||||||
|
v-show="downloadResultsFieldsMode != 'all'"
|
||||||
|
@click="downloadResultsUseAllFields()">
|
||||||
|
Use All Fields
|
||||||
|
</b-button>
|
||||||
|
<b-button type="is-primary"
|
||||||
|
v-show="downloadResultsFieldsMode != 'choose'"
|
||||||
|
@click="downloadResultsFieldsMode = 'choose'">
|
||||||
|
Choose Fields
|
||||||
|
</b-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-show="downloadResultsFieldsMode == 'choose'">
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div>
|
||||||
|
<b-field label="Excluded Fields">
|
||||||
|
<b-select multiple native-size="8"
|
||||||
|
expanded
|
||||||
|
ref="downloadResultsExcludedFields">
|
||||||
|
<option v-for="field in downloadResultsFieldsAvailable"
|
||||||
|
v-if="!downloadResultsFieldsIncluded.includes(field)"
|
||||||
|
:key="field"
|
||||||
|
:value="field">
|
||||||
|
{{ field }}
|
||||||
|
</option>
|
||||||
|
</b-select>
|
||||||
|
</b-field>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<br /><br />
|
||||||
|
<b-button style="margin: 0.5rem;"
|
||||||
|
@click="downloadResultsExcludeFields()">
|
||||||
|
<
|
||||||
|
</b-button>
|
||||||
<br />
|
<br />
|
||||||
</div>
|
<b-button style="margin: 0.5rem;"
|
||||||
|
@click="downloadResultsIncludeFields()">
|
||||||
<div class="buttons is-right">
|
>
|
||||||
<b-button type="is-primary"
|
|
||||||
v-show="downloadResultsFieldsMode != 'default'"
|
|
||||||
@click="downloadResultsUseDefaultFields()">
|
|
||||||
Use Default Fields
|
|
||||||
</b-button>
|
|
||||||
<b-button type="is-primary"
|
|
||||||
v-show="downloadResultsFieldsMode != 'all'"
|
|
||||||
@click="downloadResultsUseAllFields()">
|
|
||||||
Use All Fields
|
|
||||||
</b-button>
|
|
||||||
<b-button type="is-primary"
|
|
||||||
v-show="downloadResultsFieldsMode != 'choose'"
|
|
||||||
@click="downloadResultsFieldsMode = 'choose'">
|
|
||||||
Choose Fields
|
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<div v-show="downloadResultsFieldsMode == 'choose'">
|
<b-field label="Included Fields">
|
||||||
<div style="display: flex;">
|
<b-select multiple native-size="8"
|
||||||
<div>
|
expanded
|
||||||
<b-field label="Excluded Fields">
|
ref="downloadResultsIncludedFields">
|
||||||
<b-select multiple native-size="8"
|
<option v-for="field in downloadResultsFieldsIncluded"
|
||||||
expanded
|
:key="field"
|
||||||
ref="downloadResultsExcludedFields">
|
:value="field">
|
||||||
<option v-for="field in downloadResultsFieldsAvailable"
|
{{ field }}
|
||||||
v-if="!downloadResultsFieldsIncluded.includes(field)"
|
</option>
|
||||||
:key="field"
|
</b-select>
|
||||||
:value="field">
|
</b-field>
|
||||||
{{ field }}
|
|
||||||
</option>
|
|
||||||
</b-select>
|
|
||||||
</b-field>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<br /><br />
|
|
||||||
<b-button style="margin: 0.5rem;"
|
|
||||||
@click="downloadResultsExcludeFields()">
|
|
||||||
<
|
|
||||||
</b-button>
|
|
||||||
<br />
|
|
||||||
<b-button style="margin: 0.5rem;"
|
|
||||||
@click="downloadResultsIncludeFields()">
|
|
||||||
>
|
|
||||||
</b-button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<b-field label="Included Fields">
|
|
||||||
<b-select multiple native-size="8"
|
|
||||||
expanded
|
|
||||||
ref="downloadResultsIncludedFields">
|
|
||||||
<option v-for="field in downloadResultsFieldsIncluded"
|
|
||||||
:key="field"
|
|
||||||
:value="field">
|
|
||||||
{{ field }}
|
|
||||||
</option>
|
|
||||||
</b-select>
|
|
||||||
</b-field>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- card-content -->
|
|
||||||
|
|
||||||
<footer class="modal-card-foot">
|
</div>
|
||||||
<b-button @click="showDownloadResultsDialog = false">
|
|
||||||
Cancel
|
|
||||||
</b-button>
|
|
||||||
<once-button type="is-primary"
|
|
||||||
@click="downloadResultsSubmit()"
|
|
||||||
icon-pack="fas"
|
|
||||||
icon-left="fas fa-download"
|
|
||||||
:disabled="!downloadResultsFieldsIncluded.length"
|
|
||||||
text="Download Results">
|
|
||||||
</once-button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
</div> <!-- card-content -->
|
||||||
% endif
|
|
||||||
|
<footer class="modal-card-foot">
|
||||||
|
<b-button @click="showDownloadResultsDialog = false">
|
||||||
|
Cancel
|
||||||
|
</b-button>
|
||||||
|
<once-button type="is-primary"
|
||||||
|
@click="downloadResultsSubmit()"
|
||||||
|
icon-pack="fas"
|
||||||
|
icon-left="fas fa-download"
|
||||||
|
:disabled="!downloadResultsFieldsIncluded.length"
|
||||||
|
text="Download Results">
|
||||||
|
</once-button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</b-modal>
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## download rows for search results
|
## download rows for search results
|
||||||
% if master.has_rows and master.results_rows_downloadable and master.has_perm('download_results_rows'):
|
% if master.has_rows and master.results_rows_downloadable and master.has_perm('download_results_rows'):
|
||||||
% if use_buefy:
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="fas fa-download"
|
||||||
icon-left="fas fa-download"
|
@click="downloadResultsRows()"
|
||||||
@click="downloadResultsRows()"
|
:disabled="downloadResultsRowsButtonDisabled">
|
||||||
:disabled="downloadResultsRowsButtonDisabled">
|
{{ downloadResultsRowsButtonText }}
|
||||||
{{ downloadResultsRowsButtonText }}
|
</b-button>
|
||||||
</b-button>
|
${h.form(url('{}.download_results_rows'.format(route_prefix)), ref='downloadResultsRowsForm')}
|
||||||
${h.form(url('{}.download_results_rows'.format(route_prefix)), ref='downloadResultsRowsForm')}
|
${h.csrf_token(request)}
|
||||||
${h.csrf_token(request)}
|
${h.end_form()}
|
||||||
${h.end_form()}
|
|
||||||
% else:
|
|
||||||
${h.form(url('{}.download_results_rows'.format(route_prefix)))}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
<button type="button" id="download-row-results-button">
|
|
||||||
Download Rows for Results
|
|
||||||
</button>
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## merge 2 objects
|
## merge 2 objects
|
||||||
% if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)):
|
% if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)):
|
||||||
|
|
||||||
% if use_buefy:
|
|
||||||
${h.form(url('{}.merge'.format(route_prefix)), class_='control', **{'@submit': 'submitMergeForm'})}
|
${h.form(url('{}.merge'.format(route_prefix)), class_='control', **{'@submit': 'submitMergeForm'})}
|
||||||
% else:
|
|
||||||
${h.form(url('{}.merge'.format(route_prefix)), name='merge-things')}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
% if use_buefy:
|
<input type="hidden"
|
||||||
<input type="hidden"
|
name="uuids"
|
||||||
name="uuids"
|
:value="checkedRowUUIDs()" />
|
||||||
:value="checkedRowUUIDs()" />
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
native-type="submit"
|
||||||
native-type="submit"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="object-ungroup"
|
||||||
icon-left="object-ungroup"
|
:disabled="mergeFormSubmitting || checkedRows.length != 2">
|
||||||
:disabled="mergeFormSubmitting || checkedRows.length != 2">
|
{{ mergeFormButtonText }}
|
||||||
{{ mergeFormButtonText }}
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.hidden('uuids')}
|
|
||||||
<button type="submit" class="button">Merge 2 ${model_title_plural}</button>
|
|
||||||
% endif
|
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## enable / disable selected objects
|
## enable / disable selected objects
|
||||||
% if master.supports_set_enabled_toggle and master.has_perm('enable_disable_set'):
|
% if master.supports_set_enabled_toggle and master.has_perm('enable_disable_set'):
|
||||||
|
|
||||||
% if use_buefy:
|
${h.form(url('{}.enable_set'.format(route_prefix)), class_='control', ref='enable_selected_form')}
|
||||||
${h.form(url('{}.enable_set'.format(route_prefix)), class_='control', ref='enable_selected_form')}
|
${h.csrf_token(request)}
|
||||||
${h.csrf_token(request)}
|
${h.hidden('uuids', v_model='selected_uuids')}
|
||||||
${h.hidden('uuids', v_model='selected_uuids')}
|
<b-button :disabled="enableSelectedDisabled"
|
||||||
<b-button :disabled="enableSelectedDisabled"
|
@click="enableSelectedSubmit()">
|
||||||
@click="enableSelectedSubmit()">
|
{{ enableSelectedText }}
|
||||||
{{ enableSelectedText }}
|
</b-button>
|
||||||
</b-button>
|
${h.end_form()}
|
||||||
${h.end_form()}
|
|
||||||
% else:
|
|
||||||
${h.form(url('{}.enable_set'.format(route_prefix)), name='enable-set', class_='control')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('uuids')}
|
|
||||||
<button type="button" class="button">Enable Selected</button>
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if use_buefy:
|
${h.form(url('{}.disable_set'.format(route_prefix)), ref='disable_selected_form', class_='control')}
|
||||||
${h.form(url('{}.disable_set'.format(route_prefix)), ref='disable_selected_form', class_='control')}
|
${h.csrf_token(request)}
|
||||||
${h.csrf_token(request)}
|
${h.hidden('uuids', v_model='selected_uuids')}
|
||||||
${h.hidden('uuids', v_model='selected_uuids')}
|
<b-button :disabled="disableSelectedDisabled"
|
||||||
<b-button :disabled="disableSelectedDisabled"
|
@click="disableSelectedSubmit()">
|
||||||
@click="disableSelectedSubmit()">
|
{{ disableSelectedText }}
|
||||||
{{ disableSelectedText }}
|
</b-button>
|
||||||
</b-button>
|
${h.end_form()}
|
||||||
${h.end_form()}
|
|
||||||
% else:
|
|
||||||
${h.form(url('{}.disable_set'.format(route_prefix)), name='disable-set', class_='control')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('uuids')}
|
|
||||||
<button type="button" class="button">Disable Selected</button>
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## delete selected objects
|
## delete selected objects
|
||||||
% if master.set_deletable and master.has_perm('delete_set'):
|
% if master.set_deletable and master.has_perm('delete_set'):
|
||||||
% if use_buefy:
|
${h.form(url('{}.delete_set'.format(route_prefix)), ref='delete_selected_form', class_='control')}
|
||||||
${h.form(url('{}.delete_set'.format(route_prefix)), ref='delete_selected_form', class_='control')}
|
${h.csrf_token(request)}
|
||||||
${h.csrf_token(request)}
|
${h.hidden('uuids', v_model='selected_uuids')}
|
||||||
${h.hidden('uuids', v_model='selected_uuids')}
|
<b-button type="is-danger"
|
||||||
<b-button type="is-danger"
|
:disabled="deleteSelectedDisabled"
|
||||||
:disabled="deleteSelectedDisabled"
|
@click="deleteSelectedSubmit()"
|
||||||
@click="deleteSelectedSubmit()"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="trash">
|
||||||
icon-left="trash">
|
{{ deleteSelectedText }}
|
||||||
{{ deleteSelectedText }}
|
</b-button>
|
||||||
</b-button>
|
${h.end_form()}
|
||||||
${h.end_form()}
|
|
||||||
% else:
|
|
||||||
${h.form(url('{}.delete_set'.format(route_prefix)), name='delete-set', class_='control')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('uuids')}
|
|
||||||
<button type="button" class="button">Delete Selected</button>
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## delete search results
|
## delete search results
|
||||||
% if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)):
|
% if master.bulk_deletable and request.has_perm('{}.bulk_delete'.format(permission_prefix)):
|
||||||
% if use_buefy:
|
${h.form(url('{}.bulk_delete'.format(route_prefix)), ref='delete_results_form', class_='control')}
|
||||||
${h.form(url('{}.bulk_delete'.format(route_prefix)), ref='delete_results_form', class_='control')}
|
${h.csrf_token(request)}
|
||||||
${h.csrf_token(request)}
|
<b-button type="is-danger"
|
||||||
<b-button type="is-danger"
|
:disabled="deleteResultsDisabled"
|
||||||
:disabled="deleteResultsDisabled"
|
:title="total ? null : 'There are no results to delete'"
|
||||||
:title="total ? null : 'There are no results to delete'"
|
@click="deleteResultsSubmit()"
|
||||||
@click="deleteResultsSubmit()"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="trash">
|
||||||
icon-left="trash">
|
{{ deleteResultsText }}
|
||||||
{{ deleteResultsText }}
|
</b-button>
|
||||||
</b-button>
|
${h.end_form()}
|
||||||
${h.end_form()}
|
|
||||||
% else:
|
|
||||||
${h.form(url('{}.bulk_delete'.format(route_prefix)), name='bulk-delete', class_='control')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
<button type="button">Delete Results</button>
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
</%def>
|
</%def>
|
||||||
|
@ -516,7 +322,7 @@
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
## maybe auto-redirect to download latest results file
|
## maybe auto-redirect to download latest results file
|
||||||
% if download_results_path and use_buefy:
|
% if download_results_path:
|
||||||
ThisPage.methods.downloadResultsRedirect = function() {
|
ThisPage.methods.downloadResultsRedirect = function() {
|
||||||
location.href = '${url('{}.download_results'.format(route_prefix))}?filename=${h.os.path.basename(download_results_path)}';
|
location.href = '${url('{}.download_results'.format(route_prefix))}?filename=${h.os.path.basename(download_results_path)}';
|
||||||
}
|
}
|
||||||
|
@ -529,7 +335,7 @@
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## maybe auto-redirect to download latest "rows for results" file
|
## maybe auto-redirect to download latest "rows for results" file
|
||||||
% if download_results_rows_path and use_buefy:
|
% if download_results_rows_path:
|
||||||
ThisPage.methods.downloadResultsRowsRedirect = function() {
|
ThisPage.methods.downloadResultsRowsRedirect = function() {
|
||||||
location.href = '${url('{}.download_results_rows'.format(route_prefix))}?filename=${h.os.path.basename(download_results_rows_path)}';
|
location.href = '${url('{}.download_results_rows'.format(route_prefix))}?filename=${h.os.path.basename(download_results_rows_path)}';
|
||||||
}
|
}
|
||||||
|
@ -541,13 +347,12 @@
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
## TODO: stop checking for buefy here once we only have the one session.pop()
|
% if request.session.pop('{}.results_csv.generated'.format(route_prefix), False):
|
||||||
% if use_buefy and request.session.pop('{}.results_csv.generated'.format(route_prefix), False):
|
|
||||||
ThisPage.mounted = function() {
|
ThisPage.mounted = function() {
|
||||||
location.href = '${url('{}.results_csv_download'.format(route_prefix))}';
|
location.href = '${url('{}.results_csv_download'.format(route_prefix))}';
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
% if use_buefy and request.session.pop('{}.results_xlsx.generated'.format(route_prefix), False):
|
% if request.session.pop('{}.results_xlsx.generated'.format(route_prefix), False):
|
||||||
ThisPage.mounted = function() {
|
ThisPage.mounted = function() {
|
||||||
location.href = '${url('{}.results_xlsx_download'.format(route_prefix))}';
|
location.href = '${url('{}.results_xlsx_download'.format(route_prefix))}';
|
||||||
}
|
}
|
||||||
|
@ -793,44 +598,4 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
% if use_buefy:
|
${parent.body()}
|
||||||
${parent.body()}
|
|
||||||
|
|
||||||
% else:
|
|
||||||
## no buefy, so do the traditional thing
|
|
||||||
|
|
||||||
% if download_results_rows_path:
|
|
||||||
<div class="flash-messages">
|
|
||||||
<div class="ui-state-highlight ui-corner-all">
|
|
||||||
<span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-info"></span>
|
|
||||||
Your download should start automatically, or you can
|
|
||||||
${h.link_to("click here", '{}?filename={}'.format(url('{}.download_results_rows'.format(route_prefix)), h.os.path.basename(download_results_rows_path)))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
${grid.render_complete(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
|
|
||||||
|
|
||||||
% if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
|
|
||||||
${h.form('#', id='delete-object-form')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
|
|
||||||
## TODO: can stop checking for buefy above once this legacy chunk is gone
|
|
||||||
% if request.session.pop('{}.results_csv.generated'.format(route_prefix), False):
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
location.href = '${url('{}.results_csv_download'.format(route_prefix))}';
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
% if request.session.pop('{}.results_xlsx.generated'.format(route_prefix), False):
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
location.href = '${url('{}.results_xlsx_download'.format(route_prefix))}';
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% endif
|
|
||||||
|
|
|
@ -3,36 +3,6 @@
|
||||||
|
|
||||||
<%def name="title()">Merge 2 ${model_title_plural}</%def>
|
<%def name="title()">Merge 2 ${model_title_plural}</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('button.swap').click(function() {
|
|
||||||
$(this).button('disable').button('option', 'label', "Swapping, please wait...");
|
|
||||||
var form = $(this).parents('form');
|
|
||||||
var input = form.find('input[name="uuids"]');
|
|
||||||
var uuids = input.val().split(',');
|
|
||||||
uuids.reverse();
|
|
||||||
input.val(uuids.join(','));
|
|
||||||
form.submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('form.merge input[type="submit"]').click(function() {
|
|
||||||
$(this).button('disable').button('option', 'label', "Merging, please wait...");
|
|
||||||
var form = $(this).parents('form');
|
|
||||||
form.append($('<input type="hidden" name="commit-merge" value="yes" />'));
|
|
||||||
form.submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
@ -92,66 +62,51 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
|
<p>
|
||||||
|
You are about to <strong>merge</strong> two ${model_title} records,
|
||||||
|
(possibly) along with various related data. The tool you are using now
|
||||||
|
is somewhat generic and is not able to give you the full picture of the
|
||||||
|
implications of this merge. You are urged to proceed with caution!
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<p class="warning">
|
||||||
You are about to <strong>merge</strong> two ${model_title} records,
|
<strong>Unless you know what you're doing, a good rule of thumb (though still no
|
||||||
(possibly) along with various related data. The tool you are using now
|
guarantee) is to merge <em>only</em> if the "resulting" column is all-white.</strong>
|
||||||
is somewhat generic and is not able to give you the full picture of the
|
(You may be able to swap kept/removed in order to achieve this.)
|
||||||
implications of this merge. You are urged to proceed with caution!
|
</p>
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="warning">
|
<p>
|
||||||
<strong>Unless you know what you're doing, a good rule of thumb (though still no
|
The ${h.link_to("{} on the left".format(model_title), view_url(object_to_remove), target='_blank', class_='merge-object')}
|
||||||
guarantee) is to merge <em>only</em> if the "resulting" column is all-white.</strong>
|
will be <strong>deleted</strong>
|
||||||
(You may be able to swap kept/removed in order to achieve this.)
|
and the ${h.link_to("{} on the right".format(model_title), view_url(object_to_keep), target='_blank', class_='merge-object')}
|
||||||
</p>
|
will be <strong>kept</strong>. The one which is to be kept may also
|
||||||
|
be updated to reflect certain aspects of the one being deleted; however again
|
||||||
|
the details are up to the app logic for this type of merge and aren't fully
|
||||||
|
known to the generic tool which you're using now.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p>
|
<table class="diff">
|
||||||
The ${h.link_to("{} on the left".format(model_title), view_url(object_to_remove), target='_blank', class_='merge-object')}
|
<thead>
|
||||||
will be <strong>deleted</strong>
|
<tr>
|
||||||
and the ${h.link_to("{} on the right".format(model_title), view_url(object_to_keep), target='_blank', class_='merge-object')}
|
<th>field name</th>
|
||||||
will be <strong>kept</strong>. The one which is to be kept may also
|
<th>deleting ${model_title}</th>
|
||||||
be updated to reflect certain aspects of the one being deleted; however again
|
<th>keeping ${model_title}</th>
|
||||||
the details are up to the app logic for this type of merge and aren't fully
|
<th>resulting ${model_title}</th>
|
||||||
known to the generic tool which you're using now.
|
</tr>
|
||||||
</p>
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
% for field in sorted(merge_fields):
|
||||||
|
<tr${' class="diff"' if keep_data[field] != remove_data[field] else ''|n}>
|
||||||
|
<td class="field">${field}</td>
|
||||||
|
<td class="value remove-value">${repr(remove_data[field])}</td>
|
||||||
|
<td class="value keep-value">${repr(keep_data[field])}</td>
|
||||||
|
<td class="value result-value${' diff' if resulting_data[field] != keep_data[field] else ''}">${repr(resulting_data[field])}</td>
|
||||||
|
</tr>
|
||||||
|
% endfor
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<table class="diff">
|
<merge-buttons></merge-buttons>
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>field name</th>
|
|
||||||
<th>deleting ${model_title}</th>
|
|
||||||
<th>keeping ${model_title}</th>
|
|
||||||
<th>resulting ${model_title}</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
% for field in sorted(merge_fields):
|
|
||||||
<tr${' class="diff"' if keep_data[field] != remove_data[field] else ''|n}>
|
|
||||||
<td class="field">${field}</td>
|
|
||||||
<td class="value remove-value">${repr(remove_data[field])}</td>
|
|
||||||
<td class="value keep-value">${repr(keep_data[field])}</td>
|
|
||||||
<td class="value result-value${' diff' if resulting_data[field] != keep_data[field] else ''}">${repr(resulting_data[field])}</td>
|
|
||||||
</tr>
|
|
||||||
% endfor
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
% if use_buefy:
|
|
||||||
<merge-buttons></merge-buttons>
|
|
||||||
|
|
||||||
% else:
|
|
||||||
## no buefy; do legacy stuff
|
|
||||||
${h.form(request.current_route_url(), class_='merge')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
<div class="buttons">
|
|
||||||
${h.hidden('uuids', value='{},{}'.format(object_to_remove.uuid, object_to_keep.uuid))}
|
|
||||||
<a class="button" href="${index_url}">Whoops, nevermind</a>
|
|
||||||
<button type="button" class="swap">Swap which ${model_title} is kept/removed</button>
|
|
||||||
${h.submit('merge', "Yes, perform this merge")}
|
|
||||||
</div>
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page_template()">
|
<%def name="render_this_page_template()">
|
||||||
|
@ -177,11 +132,7 @@ ${h.end_form()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
% if use_buefy:
|
|
||||||
${h.form(request.current_route_url(), **{'@submit': 'submitMergeForm'})}
|
${h.form(request.current_route_url(), **{'@submit': 'submitMergeForm'})}
|
||||||
% else:
|
|
||||||
${h.form(request.current_route_url())}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
${h.hidden('uuids', value='{},{}'.format(object_to_remove.uuid, object_to_keep.uuid))}
|
${h.hidden('uuids', value='{},{}'.format(object_to_remove.uuid, object_to_keep.uuid))}
|
||||||
${h.hidden('commit-merge', value='yes')}
|
${h.hidden('commit-merge', value='yes')}
|
||||||
|
|
|
@ -46,12 +46,8 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
% if use_buefy:
|
<tailbone-grid :csrftoken="csrftoken">
|
||||||
<tailbone-grid :csrftoken="csrftoken">
|
</tailbone-grid>
|
||||||
</tailbone-grid>
|
|
||||||
% else:
|
|
||||||
${grid.render_complete()|n}
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -3,46 +3,6 @@
|
||||||
|
|
||||||
<%def name="title()">${index_title} » ${instance_title}</%def>
|
<%def name="title()">${index_title} » ${instance_title}</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
% if master.deletable and instance_deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
|
|
||||||
$('#context-menu a.delete-instance').on('click', function() {
|
|
||||||
if (confirm("Are you sure you wish to delete this ${model_title}?")) {
|
|
||||||
$(this).parents('form').submit();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
% if master.has_rows:
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
$('.grid-wrapper').gridwrapper();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
|
||||||
${parent.extra_styles()}
|
|
||||||
% if master.has_rows and not use_buefy:
|
|
||||||
<style type="text/css">
|
|
||||||
.grid-wrapper {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="content_title()">
|
<%def name="content_title()">
|
||||||
${instance_title}
|
${instance_title}
|
||||||
</%def>
|
</%def>
|
||||||
|
@ -54,33 +14,19 @@
|
||||||
|
|
||||||
<%def name="render_xref_helper()">
|
<%def name="render_xref_helper()">
|
||||||
% if xref_buttons or xref_links:
|
% if xref_buttons or xref_links:
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Cross-Reference</p>
|
||||||
<p class="panel-heading">Cross-Reference</p>
|
<div class="panel-block buttons">
|
||||||
<div class="panel-block buttons">
|
<div style="display: flex; flex-direction: column;">
|
||||||
<div style="display: flex; flex-direction: column;">
|
% for button in xref_buttons:
|
||||||
% for button in xref_buttons:
|
${button}
|
||||||
${button}
|
% endfor
|
||||||
% endfor
|
% for link in xref_links:
|
||||||
% for link in xref_links:
|
${link}
|
||||||
${link}
|
% endfor
|
||||||
% endfor
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="object-helper">
|
|
||||||
<h3>Cross-Reference</h3>
|
|
||||||
<div class="object-helper-content">
|
|
||||||
% for button in xref_buttons:
|
|
||||||
${button}
|
|
||||||
% endfor
|
|
||||||
% for link in xref_links:
|
|
||||||
${link}
|
|
||||||
% endfor
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
% endif
|
</div>
|
||||||
|
</nav>
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -91,63 +37,37 @@
|
||||||
% if master.has_versions and request.rattail_config.versioning_enabled() and request.has_perm('{}.versions'.format(permission_prefix)):
|
% if master.has_versions and request.rattail_config.versioning_enabled() and request.has_perm('{}.versions'.format(permission_prefix)):
|
||||||
<li>${h.link_to("Version History", action_url('versions', instance))}</li>
|
<li>${h.link_to("Version History", action_url('versions', instance))}</li>
|
||||||
% endif
|
% endif
|
||||||
% if not use_buefy and master.editable and instance_editable and master.has_perm('edit'):
|
|
||||||
<li>${h.link_to("Edit this {}".format(model_title), action_url('edit', instance))}</li>
|
|
||||||
% endif
|
|
||||||
${self.context_menu_item_delete()}
|
|
||||||
% if not use_buefy and master.creatable and master.show_create_link and master.has_perm('create'):
|
|
||||||
% if master.creates_multiple:
|
|
||||||
<li>${h.link_to("Create new {}".format(model_title_plural), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% else:
|
|
||||||
<li>${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}</li>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
% if not use_buefy and master.cloneable and master.has_perm('clone'):
|
|
||||||
<li>${h.link_to("Clone this as new {}".format(model_title), url('{}.clone'.format(route_prefix), uuid=instance.uuid))}</li>
|
|
||||||
% endif
|
|
||||||
% if master.touchable and request.has_perm('{}.touch'.format(permission_prefix)):
|
% if master.touchable and request.has_perm('{}.touch'.format(permission_prefix)):
|
||||||
<li>${h.link_to("\"Touch\" this {}".format(model_title), master.get_action_url('touch', instance))}</li>
|
<li>${h.link_to("\"Touch\" this {}".format(model_title), master.get_action_url('touch', instance))}</li>
|
||||||
% endif
|
% endif
|
||||||
% if not use_buefy and master.has_rows and master.rows_downloadable_csv and master.has_perm('row_results_csv'):
|
|
||||||
<li>${h.link_to("Download row results as CSV", master.get_action_url('row_results_csv', instance))}</li>
|
|
||||||
% endif
|
|
||||||
% if not use_buefy and master.has_rows and master.rows_downloadable_xlsx and master.has_perm('row_results_xlsx'):
|
|
||||||
<li>${h.link_to("Download row results as XLSX", master.get_action_url('row_results_xlsx', instance))}</li>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_row_grid_tools()">
|
<%def name="render_row_grid_tools()">
|
||||||
${rows_grid_tools}
|
${rows_grid_tools}
|
||||||
% if use_buefy:
|
% if master.rows_downloadable_xlsx and master.has_perm('row_results_xlsx'):
|
||||||
% if master.rows_downloadable_xlsx and master.has_perm('row_results_xlsx'):
|
<b-button tag="a" href="${master.get_action_url('row_results_xlsx', instance)}"
|
||||||
<b-button tag="a" href="${master.get_action_url('row_results_xlsx', instance)}"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="download">
|
||||||
icon-left="download">
|
Download Results XLSX
|
||||||
Download Results XLSX
|
</b-button>
|
||||||
</b-button>
|
% endif
|
||||||
% endif
|
% if master.rows_downloadable_csv and master.has_perm('row_results_csv'):
|
||||||
% if master.rows_downloadable_csv and master.has_perm('row_results_csv'):
|
<b-button tag="a" href="${master.get_action_url('row_results_csv', instance)}"
|
||||||
<b-button tag="a" href="${master.get_action_url('row_results_csv', instance)}"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="download">
|
||||||
icon-left="download">
|
Download Results CSV
|
||||||
Download Results CSV
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page()">
|
<%def name="render_this_page()">
|
||||||
${parent.render_this_page()}
|
${parent.render_this_page()}
|
||||||
% if master.has_rows:
|
% if master.has_rows:
|
||||||
% if use_buefy:
|
<br />
|
||||||
<br />
|
% if rows_title:
|
||||||
% if rows_title:
|
<h4 class="block is-size-4">${rows_title}</h4>
|
||||||
<h4 class="block is-size-4">${rows_title}</h4>
|
|
||||||
% endif
|
|
||||||
${self.render_row_grid_component()}
|
|
||||||
% else:
|
|
||||||
${rows_grid|n}
|
|
||||||
% endif
|
% endif
|
||||||
|
${self.render_row_grid_component()}
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,6 @@
|
||||||
% if master.rows_editable and instance_editable and request.has_perm('{}.edit'.format(permission_prefix)):
|
% if master.rows_editable and instance_editable and request.has_perm('{}.edit'.format(permission_prefix)):
|
||||||
<li>${h.link_to("Edit this {}".format(model_title), action_url('edit', instance))}</li>
|
<li>${h.link_to("Edit this {}".format(model_title), action_url('edit', instance))}</li>
|
||||||
% endif
|
% endif
|
||||||
% if not use_buefy and instance_deletable and master.has_perm('delete_row'):
|
|
||||||
<li>${h.link_to("Delete this {}".format(model_title), action_url('delete', instance))}</li>
|
|
||||||
% endif
|
|
||||||
% if rows_creatable and request.has_perm('{}.create'.format(permission_prefix)):
|
% if rows_creatable and request.has_perm('{}.create'.format(permission_prefix)):
|
||||||
<li>${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}</li>
|
<li>${h.link_to("Create a new {}".format(model_title), url('{}.create'.format(route_prefix)))}</li>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -3,15 +3,6 @@
|
||||||
|
|
||||||
<%def name="title()">Message Archive</%def>
|
<%def name="title()">Message Archive</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
destination = "Inbox";
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
${parent.context_menu_items()}
|
${parent.context_menu_items()}
|
||||||
<li>${h.link_to("Go to my Message Inbox", url('messages.inbox'))}</li>
|
<li>${h.link_to("Go to my Message Inbox", url('messages.inbox'))}</li>
|
||||||
|
|
|
@ -2,148 +2,26 @@
|
||||||
<%inherit file="/master/create.mako" />
|
<%inherit file="/master/create.mako" />
|
||||||
<%namespace file="/messages/recipients.mako" import="message_recipients_template" />
|
<%namespace file="/messages/recipients.mako" import="message_recipients_template" />
|
||||||
|
|
||||||
<%def name="content_title()">${parent.content_title() if not use_buefy else ''}</%def>
|
<%def name="content_title()"></%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
% if use_buefy:
|
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.message_recipients.js'))}
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.message_recipients.js'))}
|
|
||||||
% else:
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/lib/tag-it.min.js'))}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var recipient_mappings = new Map([
|
|
||||||
<% last = len(available_recipients) %>
|
|
||||||
% for i, recip in enumerate(available_recipients, 1):
|
|
||||||
<% uuid, entry = recip %>
|
|
||||||
['${uuid}', ${json.dumps(entry)|n}]${',' if i < last else ''}
|
|
||||||
% endfor
|
|
||||||
]);
|
|
||||||
|
|
||||||
// validate message before sending
|
|
||||||
function validate_message_form() {
|
|
||||||
var form = $('#deform');
|
|
||||||
|
|
||||||
if (! form.find('input[name="set_recipients"]').val()) {
|
|
||||||
alert("You must specify some recipient(s) for the message.");
|
|
||||||
$('.set_recipients input').data('ui-tagit').tagInput.focus();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! form.find('input[name="subject"]').val()) {
|
|
||||||
alert("You must provide a subject for the message.");
|
|
||||||
form.find('input[name="subject"]').focus();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
var recipients = $('.set_recipients input');
|
|
||||||
|
|
||||||
recipients.tagit({
|
|
||||||
|
|
||||||
autocomplete: {
|
|
||||||
delay: 0,
|
|
||||||
minLength: 2,
|
|
||||||
autoFocus: true,
|
|
||||||
removeConfirmation: true,
|
|
||||||
|
|
||||||
source: function(request, response) {
|
|
||||||
var term = request.term.toLowerCase();
|
|
||||||
var data = [];
|
|
||||||
recipient_mappings.forEach(function(name, uuid) {
|
|
||||||
if (!name.toLowerCase && name.name) {
|
|
||||||
name = name.name;
|
|
||||||
}
|
|
||||||
if (name.toLowerCase().indexOf(term) >= 0) {
|
|
||||||
data.push({value: uuid, label: name});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
response(data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeTagAdded: ${self.before_tag_added()},
|
|
||||||
|
|
||||||
beforeTagRemoved: function(event, ui) {
|
|
||||||
|
|
||||||
// Unfortunately we're responsible for cleaning up the hidden
|
|
||||||
// field, since the values there do not match the tag labels.
|
|
||||||
var tags = recipients.tagit('assignedTags');
|
|
||||||
var uuid = ui.tag.data('uuid');
|
|
||||||
tags = tags.filter(function(element) {
|
|
||||||
return element != uuid;
|
|
||||||
});
|
|
||||||
recipients.data('ui-tagit')._updateSingleTagsField(tags);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// set focus to recipients field
|
|
||||||
recipients.data('ui-tagit').tagInput.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
${self.validate_message_js()}
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="validate_message_js()">
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
$('#new-message').submit(function() {
|
|
||||||
return validate_message_form();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if use_buefy:
|
|
||||||
<style type="text/css">
|
|
||||||
|
|
||||||
.this-page-content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.this-page-content .buttons {
|
|
||||||
margin-left: 20rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
% else:
|
|
||||||
${h.stylesheet_link(request.static_url('tailbone:static/css/jquery.tagit.css'))}
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
|
||||||
.recipients input {
|
.this-page-content {
|
||||||
min-width: 525px;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subject input {
|
.this-page-content .buttons {
|
||||||
min-width: 540px;
|
margin-left: 20rem;
|
||||||
}
|
|
||||||
|
|
||||||
.body textarea {
|
|
||||||
min-width: 540px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="before_tag_added()">
|
|
||||||
function(event, ui) {
|
|
||||||
|
|
||||||
// Lookup the name in cached mapping, and show that on the tag, instead
|
|
||||||
// of the UUID. The tagit widget should take care of keeping the
|
|
||||||
// hidden field in sync for us, still using the UUID.
|
|
||||||
var uuid = ui.tagLabel;
|
|
||||||
var name = recipient_mappings.get(uuid);
|
|
||||||
ui.tag.find('.tagit-label').html(name);
|
|
||||||
}
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
|
|
|
@ -3,15 +3,6 @@
|
||||||
|
|
||||||
<%def name="title()">Message Inbox</%def>
|
<%def name="title()">Message Inbox</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
destination = "Archive";
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
${parent.context_menu_items()}
|
${parent.context_menu_items()}
|
||||||
<li>${h.link_to("Go to my Message Archive", url('messages.archive'))}</li>
|
<li>${h.link_to("Go to my Message Archive", url('messages.archive'))}</li>
|
||||||
|
|
|
@ -1,52 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/index.mako" />
|
<%inherit file="/master/index.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var destination = null;
|
|
||||||
|
|
||||||
function update_move_button() {
|
|
||||||
var count = $('.grid tr:not(.header) td.checkbox input:checked').length;
|
|
||||||
$('form[name="move-selected"] button')
|
|
||||||
.button('option', 'label', "Move " + count + " selected to " + destination)
|
|
||||||
.button('option', 'disabled', count < 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
update_move_button();
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('change', 'tr.header td.checkbox input', function() {
|
|
||||||
update_move_button();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('click', 'tr:not(.header) td.checkbox input', function() {
|
|
||||||
update_move_button();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('form[name="move-selected"]').submit(function() {
|
|
||||||
var uuids = [];
|
|
||||||
$('.grid tr:not(.header) td.checkbox input:checked').each(function() {
|
|
||||||
uuids.push($(this).parents('tr:first').data('uuid'));
|
|
||||||
});
|
|
||||||
if (! uuids.length) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$(this).find('[name="uuids"]').val(uuids.toString());
|
|
||||||
$(this).find('button')
|
|
||||||
.button('option', 'label', "Moving " + uuids.length + " messages to " + destination + "...")
|
|
||||||
.button('disable');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
% if request.has_perm('messages.create'):
|
% if request.has_perm('messages.create'):
|
||||||
<li>${h.link_to("Send a new Message", url('messages.create'))}</li>
|
<li>${h.link_to("Send a new Message", url('messages.create'))}</li>
|
||||||
|
@ -55,25 +9,16 @@
|
||||||
|
|
||||||
<%def name="grid_tools()">
|
<%def name="grid_tools()">
|
||||||
% if request.matched_route.name in ('messages.inbox', 'messages.archive'):
|
% if request.matched_route.name in ('messages.inbox', 'messages.archive'):
|
||||||
% if use_buefy:
|
${h.form(url('messages.move_bulk'), **{'@submit': 'moveMessagesSubmit'})}
|
||||||
${h.form(url('messages.move_bulk'), **{'@submit': 'moveMessagesSubmit'})}
|
${h.csrf_token(request)}
|
||||||
${h.csrf_token(request)}
|
${h.hidden('destination', value='archive' if request.matched_route.name == 'messages.inbox' else 'inbox')}
|
||||||
${h.hidden('destination', value='archive' if request.matched_route.name == 'messages.inbox' else 'inbox')}
|
${h.hidden('uuids', v_model='selected_uuids')}
|
||||||
${h.hidden('uuids', v_model='selected_uuids')}
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
native-type="submit"
|
||||||
native-type="submit"
|
:disabled="moveMessagesSubmitting || !checkedRows.length">
|
||||||
:disabled="moveMessagesSubmitting || !checkedRows.length">
|
{{ moveMessagesTextCurrent }}
|
||||||
{{ moveMessagesTextCurrent }}
|
</b-button>
|
||||||
</b-button>
|
${h.end_form()}
|
||||||
${h.end_form()}
|
|
||||||
% else:
|
|
||||||
${h.form(url('messages.move_bulk'), name='move-selected')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('destination', value='archive' if request.matched_route.name == 'messages.inbox' else 'inbox')}
|
|
||||||
${h.hidden('uuids')}
|
|
||||||
<button type="submit">Move 0 selected to ${'Archive' if request.matched_route.name == 'messages.inbox' else 'Inbox'}</button>
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
|
@ -1,66 +1,20 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('.field-wrapper.recipients .more').click(function() {
|
|
||||||
$(this).hide();
|
|
||||||
$(this).siblings('.everyone').css('display', 'inline-block');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.field-wrapper.recipients .everyone').click(function() {
|
|
||||||
$(this).hide();
|
|
||||||
$(this).siblings('.more').show();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if use_buefy:
|
|
||||||
<style type="text/css">
|
|
||||||
.everyone {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.tailbone-message-body {
|
|
||||||
margin: 1rem auto;
|
|
||||||
min-height: 10rem;
|
|
||||||
}
|
|
||||||
.tailbone-message-body p {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
% else:
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.recipients .everyone {
|
.everyone {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
.message-tools {
|
.tailbone-message-body {
|
||||||
margin-bottom: 15px;
|
margin: 1rem auto;
|
||||||
|
min-height: 10rem;
|
||||||
}
|
}
|
||||||
.message-body {
|
.tailbone-message-body p {
|
||||||
border-top: 1px solid black;
|
margin-bottom: 1rem;
|
||||||
border-bottom: 1px solid black;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
padding: 0 5em;
|
|
||||||
white-space: pre-line;
|
|
||||||
}
|
|
||||||
.message-body p {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
|
@ -86,43 +40,29 @@
|
||||||
|
|
||||||
<%def name="message_tools()">
|
<%def name="message_tools()">
|
||||||
% if recipient:
|
% if recipient:
|
||||||
% if use_buefy:
|
<div class="buttons">
|
||||||
<div class="buttons">
|
% if request.has_perm('messages.create'):
|
||||||
% if request.has_perm('messages.create'):
|
<once-button type="is-primary"
|
||||||
<once-button type="is-primary"
|
tag="a" href="${url('messages.reply', uuid=instance.uuid)}"
|
||||||
tag="a" href="${url('messages.reply', uuid=instance.uuid)}"
|
text="Reply">
|
||||||
text="Reply">
|
</once-button>
|
||||||
</once-button>
|
<once-button type="is-primary"
|
||||||
<once-button type="is-primary"
|
tag="a" href="${url('messages.reply_all', uuid=instance.uuid)}"
|
||||||
tag="a" href="${url('messages.reply_all', uuid=instance.uuid)}"
|
text="Reply to All">
|
||||||
text="Reply to All">
|
</once-button>
|
||||||
</once-button>
|
% endif
|
||||||
% endif
|
% if recipient.status == enum.MESSAGE_STATUS_INBOX:
|
||||||
% if recipient.status == enum.MESSAGE_STATUS_INBOX:
|
<once-button type="is-primary"
|
||||||
<once-button type="is-primary"
|
tag="a" href="${url('messages.move', uuid=instance.uuid)}?dest=archive"
|
||||||
tag="a" href="${url('messages.move', uuid=instance.uuid)}?dest=archive"
|
text="Move to Archive">
|
||||||
text="Move to Archive">
|
</once-button>
|
||||||
</once-button>
|
% else:
|
||||||
% else:
|
<once-button type="is-primary"
|
||||||
<once-button type="is-primary"
|
tag="a" href="${url('messages.move', uuid=instance.uuid)}?dest=inbox"
|
||||||
tag="a" href="${url('messages.move', uuid=instance.uuid)}?dest=inbox"
|
text="Move to Inbox">
|
||||||
text="Move to Inbox">
|
</once-button>
|
||||||
</once-button>
|
% endif
|
||||||
% endif
|
</div>
|
||||||
</div>
|
|
||||||
% else:
|
|
||||||
<div class="message-tools">
|
|
||||||
% if request.has_perm('messages.create'):
|
|
||||||
${h.link_to("Reply", url('messages.reply', uuid=instance.uuid), class_='button')}
|
|
||||||
${h.link_to("Reply to All", url('messages.reply_all', uuid=instance.uuid), class_='button')}
|
|
||||||
% endif
|
|
||||||
% if recipient.status == enum.MESSAGE_STATUS_INBOX:
|
|
||||||
${h.link_to("Move to Archive", url('messages.move', uuid=instance.uuid) + '?dest=archive', class_='button')}
|
|
||||||
% else:
|
|
||||||
${h.link_to("Move to Inbox", url('messages.move', uuid=instance.uuid) + '?dest=inbox', class_='button')}
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -132,22 +72,14 @@
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
${parent.page_content()}
|
${parent.page_content()}
|
||||||
% if use_buefy:
|
<br />
|
||||||
<br />
|
<div style="margin-left: 5rem;">
|
||||||
<div style="margin-left: 5rem;">
|
${self.message_tools()}
|
||||||
${self.message_tools()}
|
<div class="tailbone-message-body">
|
||||||
<div class="tailbone-message-body">
|
${self.message_body()}
|
||||||
${self.message_body()}
|
</div>
|
||||||
</div>
|
${self.message_tools()}
|
||||||
${self.message_tools()}
|
</div>
|
||||||
</div>
|
|
||||||
% else:
|
|
||||||
${self.message_tools()}
|
|
||||||
<div class="message-body">
|
|
||||||
${self.message_body()}
|
|
||||||
</div>
|
|
||||||
${self.message_tools()}
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
|
|
|
@ -1,82 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/batch/create.mako" />
|
<%inherit file="/batch/create.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
## TODO: deprecate / remove
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${self.func_show_mode()}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var purchases_field = '${purchases_field}';
|
|
||||||
var purchases = null; // TODO: where is this used?
|
|
||||||
|
|
||||||
function vendor_selected(uuid, name) {
|
|
||||||
## var mode = $('.mode select').val();
|
|
||||||
## if (mode == ${enum.PURCHASE_BATCH_MODE_RECEIVING} || mode == ${enum.PURCHASE_BATCH_MODE_COSTING}) {
|
|
||||||
## var purchases = $('.purchase_uuid select');
|
|
||||||
## purchases.empty();
|
|
||||||
##
|
|
||||||
## var data = {'vendor_uuid': uuid, 'mode': mode};
|
|
||||||
## $.get('${url('purchases.batch.eligible_purchases')}', data, function(data) {
|
|
||||||
## if (data.error) {
|
|
||||||
## alert(data.error);
|
|
||||||
## } else {
|
|
||||||
## $.each(data.purchases, function(i, purchase) {
|
|
||||||
## purchases.append($('<option value="' + purchase.key + '">' + purchase.display + '</option>'));
|
|
||||||
## });
|
|
||||||
## }
|
|
||||||
## });
|
|
||||||
##
|
|
||||||
## // TODO: apparently refresh doesn't work right?
|
|
||||||
## // http://stackoverflow.com/a/10280078
|
|
||||||
## // purchases.selectmenu('refresh');
|
|
||||||
## purchases.selectmenu('destroy').selectmenu();
|
|
||||||
## }
|
|
||||||
}
|
|
||||||
|
|
||||||
function vendor_cleared() {
|
|
||||||
var purchases = $('.purchase_uuid select');
|
|
||||||
purchases.empty();
|
|
||||||
|
|
||||||
// TODO: apparently refresh doesn't work right?
|
|
||||||
// http://stackoverflow.com/a/10280078
|
|
||||||
// purchases.selectmenu('refresh');
|
|
||||||
purchases.selectmenu('destroy').selectmenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('.field-wrapper.mode select').selectmenu({
|
|
||||||
change: function(event, ui) {
|
|
||||||
show_mode(ui.item.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
show_mode(${enum.PURCHASE_BATCH_MODE_ORDERING});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="func_show_mode()">
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
// TODO: mode is presumably null here..
|
|
||||||
function show_mode(mode) {
|
|
||||||
$('.field-wrapper.store_uuid').show();
|
|
||||||
$('.field-wrapper.' + purchases_field).hide();
|
|
||||||
$('.field-wrapper.department_uuid').show();
|
|
||||||
$('.field-wrapper.buyer_uuid').show();
|
|
||||||
$('.field-wrapper.date_ordered').show();
|
|
||||||
$('.field-wrapper.date_received').hide();
|
|
||||||
$('.field-wrapper.po_number').show();
|
|
||||||
$('.field-wrapper.invoice_date').hide();
|
|
||||||
$('.field-wrapper.invoice_number').hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -3,63 +3,6 @@
|
||||||
|
|
||||||
<%def name="title()">Ordering Worksheet</%def>
|
<%def name="title()">Ordering Worksheet</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/numeric.js'))}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var submitting = false;
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('.order-form td.current-order input').focus(function(event) {
|
|
||||||
$(this).parents('tr:first').addClass('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.order-form td.current-order input').blur(function(event) {
|
|
||||||
$(this).parents('tr:first').removeClass('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.order-form td.current-order input').keydown(function(event) {
|
|
||||||
if (key_allowed(event) || key_modifies(event)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (event.which == 13) {
|
|
||||||
if (! submitting) {
|
|
||||||
submitting = true;
|
|
||||||
var row = $(this).parents('tr:first');
|
|
||||||
var form = $('#item-update-form');
|
|
||||||
form.find('[name="product_uuid"]').val(row.data('uuid'));
|
|
||||||
form.find('[name="cases_ordered"]').val(row.find('input[name^="cases_ordered_"]').val() || '0');
|
|
||||||
form.find('[name="units_ordered"]').val(row.find('input[name^="units_ordered_"]').val() || '0');
|
|
||||||
$.post(form.attr('action'), form.serialize(), function(data) {
|
|
||||||
if (data.error) {
|
|
||||||
alert(data.error);
|
|
||||||
} else {
|
|
||||||
if (data.row_cases_ordered || data.row_units_ordered) {
|
|
||||||
row.find('input[name^="cases_ordered_"]').val(data.row_cases_ordered);
|
|
||||||
row.find('input[name^="units_ordered_"]').val(data.row_units_ordered);
|
|
||||||
row.find('td.po-total').html(data.row_po_total_calculated);
|
|
||||||
} else {
|
|
||||||
row.find('input[name^="cases_ordered_"]').val('');
|
|
||||||
row.find('input[name^="units_ordered_"]').val('');
|
|
||||||
row.find('td.po-total').html('');
|
|
||||||
}
|
|
||||||
$('.po-total .field').html(data.batch_po_total_calculated);
|
|
||||||
}
|
|
||||||
submitting = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
@ -187,10 +130,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
% for i, cost in enumerate(subdepartment._order_costs, 1):
|
% for i, cost in enumerate(subdepartment._order_costs, 1):
|
||||||
<tr data-uuid="${cost.product_uuid}" class="${'even' if i % 2 == 0 else 'odd'}"
|
<tr data-uuid="${cost.product_uuid}" class="${'even' if i % 2 == 0 else 'odd'}"
|
||||||
% if use_buefy:
|
:class="{active: activeUUID == '${cost.uuid}'}">
|
||||||
:class="{active: activeUUID == '${cost.uuid}'}"
|
|
||||||
% endif
|
|
||||||
>
|
|
||||||
${self.order_form_row(cost)}
|
${self.order_form_row(cost)}
|
||||||
% for data in history:
|
% for data in history:
|
||||||
<td class="scratch_pad">
|
<td class="scratch_pad">
|
||||||
|
@ -216,34 +156,21 @@
|
||||||
% endfor
|
% endfor
|
||||||
% if not ignore_cases:
|
% if not ignore_cases:
|
||||||
<td class="current-order">
|
<td class="current-order">
|
||||||
% if use_buefy:
|
<numeric-input v-model="worksheet.cost_${cost.uuid}_cases"
|
||||||
<numeric-input v-model="worksheet.cost_${cost.uuid}_cases"
|
|
||||||
@focus="activeUUID = '${cost.uuid}'; $event.target.select()"
|
|
||||||
@blur="activeUUID = null"
|
|
||||||
@keydown.native="inputKeydown($event, '${cost.uuid}', '${cost.product_uuid}')">
|
|
||||||
</numeric-input>
|
|
||||||
% else:
|
|
||||||
${h.text('cases_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.cases_ordered or 0) if cost._batchrow else None)}
|
|
||||||
% endif
|
|
||||||
</td>
|
|
||||||
% endif
|
|
||||||
<td class="current-order">
|
|
||||||
% if use_buefy:
|
|
||||||
<numeric-input v-model="worksheet.cost_${cost.uuid}_units"
|
|
||||||
@focus="activeUUID = '${cost.uuid}'; $event.target.select()"
|
@focus="activeUUID = '${cost.uuid}'; $event.target.select()"
|
||||||
@blur="activeUUID = null"
|
@blur="activeUUID = null"
|
||||||
@keydown.native="inputKeydown($event, '${cost.uuid}', '${cost.product_uuid}')">
|
@keydown.native="inputKeydown($event, '${cost.uuid}', '${cost.product_uuid}')">
|
||||||
</numeric-input>
|
</numeric-input>
|
||||||
% else:
|
</td>
|
||||||
${h.text('units_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.units_ordered or 0) if cost._batchrow else None)}
|
|
||||||
% endif
|
|
||||||
</td>
|
|
||||||
## TODO: should not fall back to po_total
|
|
||||||
% if use_buefy:
|
|
||||||
<td class="po-total">{{ worksheet.cost_${cost.uuid}_total_display }}</td>
|
|
||||||
% else:
|
|
||||||
<td class="po-total">${'${:0,.2f}'.format(cost._batchrow.po_total_calculated or cost._batchrow.po_total or 0) if cost._batchrow else ''}</td>
|
|
||||||
% endif
|
% endif
|
||||||
|
<td class="current-order">
|
||||||
|
<numeric-input v-model="worksheet.cost_${cost.uuid}_units"
|
||||||
|
@focus="activeUUID = '${cost.uuid}'; $event.target.select()"
|
||||||
|
@blur="activeUUID = null"
|
||||||
|
@keydown.native="inputKeydown($event, '${cost.uuid}', '${cost.product_uuid}')">
|
||||||
|
</numeric-input>
|
||||||
|
</td>
|
||||||
|
<td class="po-total">{{ worksheet.cost_${cost.uuid}_total_display }}</td>
|
||||||
${self.extra_td(cost)}
|
${self.extra_td(cost)}
|
||||||
</tr>
|
</tr>
|
||||||
% endfor
|
% endfor
|
||||||
|
@ -269,55 +196,7 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
% if use_buefy:
|
<ordering-worksheet></ordering-worksheet>
|
||||||
<ordering-worksheet></ordering-worksheet>
|
|
||||||
% else:
|
|
||||||
<div class="form-wrapper">
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Vendor</label>
|
|
||||||
<div class="field">${h.link_to(vendor, url('vendors.view', uuid=vendor.uuid))}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Vendor Email</label>
|
|
||||||
<div class="field">${vendor.email or ''}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Vendor Fax</label>
|
|
||||||
<div class="field">${vendor.fax_number or ''}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Vendor Contact</label>
|
|
||||||
<div class="field">${vendor.contact or ''}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Vendor Phone</label>
|
|
||||||
<div class="field">${vendor.phone or ''}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${self.extra_vendor_fields()}
|
|
||||||
|
|
||||||
<div class="field-wrapper po-total">
|
|
||||||
<label>PO Total</label>
|
|
||||||
## TODO: should not fall back to po_total
|
|
||||||
<div class="field">$${'{:0,.2f}'.format(batch.po_total_calculated or batch.po_total or 0)}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div><!-- form-wrapper -->
|
|
||||||
|
|
||||||
${self.order_form_grid()}
|
|
||||||
|
|
||||||
${h.form(url('ordering.worksheet_update', uuid=batch.uuid), id='item-update-form', style='display: none;')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('product_uuid')}
|
|
||||||
${h.hidden('cases_ordered')}
|
|
||||||
${h.hidden('units_ordered')}
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page_template()">
|
<%def name="render_this_page_template()">
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
<%def name="grid_tools()">
|
<%def name="grid_tools()">
|
||||||
|
|
||||||
% if master.mergeable and master.has_perm('request_merge'):
|
% if master.mergeable and master.has_perm('request_merge'):
|
||||||
% if use_buefy:
|
|
||||||
<b-button @click="showMergeRequest()"
|
<b-button @click="showMergeRequest()"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="object-ungroup"
|
icon-left="object-ungroup"
|
||||||
|
@ -57,7 +56,6 @@
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
${parent.grid_tools()}
|
${parent.grid_tools()}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
${parent.page_content()}
|
${parent.page_content()}
|
||||||
% if not instance.merged and request.has_perm('people.merge'):
|
% if not instance.merged and request.has_perm('people.merge'):
|
||||||
% if use_buefy:
|
|
||||||
${h.form(url('people.merge'), **{'@submit': 'submitMergeForm'})}
|
${h.form(url('people.merge'), **{'@submit': 'submitMergeForm'})}
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
${h.hidden('uuids', value=','.join([instance.removing_uuid, instance.keeping_uuid]))}
|
${h.hidden('uuids', value=','.join([instance.removing_uuid, instance.keeping_uuid]))}
|
||||||
|
@ -16,7 +15,6 @@
|
||||||
{{ mergeFormButtonText }}
|
{{ mergeFormButtonText }}
|
||||||
</b-button>
|
</b-button>
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
|
@ -2,25 +2,6 @@
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
<%namespace file="/util.mako" import="view_profiles_helper" />
|
<%namespace file="/util.mako" import="view_profiles_helper" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy and not instance.users and request.has_perm('users.create'):
|
|
||||||
<script type="text/javascript">
|
|
||||||
## TODO: should do this differently for Buefy themes
|
|
||||||
$(function() {
|
|
||||||
$('#make-user').click(function() {
|
|
||||||
if (confirm("Really make a user account for this person?")) {
|
|
||||||
% if not use_buefy:
|
|
||||||
disable_button(this);
|
|
||||||
% endif
|
|
||||||
$('form[name="make-user-form"]').submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="object_helpers()">
|
<%def name="object_helpers()">
|
||||||
${parent.object_helpers()}
|
${parent.object_helpers()}
|
||||||
${view_profiles_helper([instance])}
|
${view_profiles_helper([instance])}
|
||||||
|
@ -52,11 +33,7 @@
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
${parent.page_content()}
|
${parent.page_content()}
|
||||||
% if not instance.users and request.has_perm('users.create'):
|
% if not instance.users and request.has_perm('users.create'):
|
||||||
% if use_buefy:
|
${h.form(url('people.make_user'), ref='makeUserForm')}
|
||||||
${h.form(url('people.make_user'), ref='makeUserForm')}
|
|
||||||
% else:
|
|
||||||
${h.form(url('people.make_user'), name='make-user-form')}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
${h.hidden('person_uuid', value=instance.uuid)}
|
${h.hidden('person_uuid', value=instance.uuid)}
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
|
|
|
@ -3,77 +3,10 @@
|
||||||
|
|
||||||
<%def name="title()">Find ${model_title_plural} by Permission</%def>
|
<%def name="title()">Find ${model_title_plural} by Permission</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
<% gcount = len(permissions) %>
|
|
||||||
var permissions_by_group = {
|
|
||||||
% for g, (gkey, group) in enumerate(permissions, 1):
|
|
||||||
<% pcount = len(group['perms']) %>
|
|
||||||
'${gkey}': {
|
|
||||||
% for p, (pkey, perm) in enumerate(group['perms'], 1):
|
|
||||||
'${pkey}': "${perm['label']}"${',' if p < pcount else ''}
|
|
||||||
% endfor
|
|
||||||
}${',' if g < gcount else ''}
|
|
||||||
% endfor
|
|
||||||
};
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#permission_group').selectmenu({
|
|
||||||
change: function(event, ui) {
|
|
||||||
var perms = $('#permission');
|
|
||||||
perms.find('option:first').siblings('option').remove();
|
|
||||||
$.each(permissions_by_group[ui.item.value], function(key, label) {
|
|
||||||
perms.append($('<option value="' + key + '">' + label + '</option>'));
|
|
||||||
});
|
|
||||||
perms.selectmenu('refresh');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#permission').selectmenu();
|
|
||||||
|
|
||||||
$('#find-by-perm-form').submit(function() {
|
|
||||||
$('.grid').remove();
|
|
||||||
$(this).find('#submit').button('disable').button('option', 'label', "Searching, please wait...");
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
% if use_buefy:
|
<find-principals :permission-groups="permissionGroups"
|
||||||
<find-principals :permission-groups="permissionGroups"
|
:sorted-groups="sortedGroups">
|
||||||
:sorted-groups="sortedGroups">
|
</find-principals>
|
||||||
</find-principals>
|
|
||||||
% else:
|
|
||||||
## not buefy
|
|
||||||
${h.form(request.current_route_url(), id='find-by-perm-form')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
|
|
||||||
<div class="form">
|
|
||||||
${self.wtfield(form, 'permission_group')}
|
|
||||||
${self.wtfield(form, 'permission')}
|
|
||||||
<div class="buttons">
|
|
||||||
${h.submit('submit', "Find {}".format(model_title_plural))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${h.end_form()}
|
|
||||||
|
|
||||||
% if principals is not None:
|
|
||||||
<div class="grid half">
|
|
||||||
<br />
|
|
||||||
<h2>${model_title_plural} with that permission (${len(principals)} total):</h2>
|
|
||||||
${self.principal_table()}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page_template()">
|
<%def name="render_this_page_template()">
|
||||||
|
|
|
@ -7,66 +7,22 @@
|
||||||
<li>${h.link_to("Back to Products", url('products'))}</li>
|
<li>${h.link_to("Back to Products", url('products'))}</li>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('select[name="batch_type"]').on('selectmenuchange', function(event, ui) {
|
|
||||||
$('.params-wrapper').hide();
|
|
||||||
$('.params-wrapper.' + ui.item.value).show();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.params-wrapper.' + $('select[name="batch_type"]').val()).show();
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
|
||||||
${parent.extra_styles()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<style type="text/css">
|
|
||||||
.params-wrapper {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="render_deform_field(form, field)">
|
<%def name="render_deform_field(form, field)">
|
||||||
% if use_buefy:
|
<b-field horizontal
|
||||||
<b-field horizontal
|
% if field.description:
|
||||||
% if field.description:
|
message="${field.description}"
|
||||||
message="${field.description}"
|
% endif
|
||||||
% endif
|
% if field.error:
|
||||||
% if field.error:
|
type="is-danger"
|
||||||
type="is-danger"
|
:message='${form.messages_json(field.error.messages())|n}'
|
||||||
:message='${form.messages_json(field.error.messages())|n}'
|
% endif
|
||||||
% endif
|
label="${field.title}">
|
||||||
label="${field.title}">
|
${field.serialize()|n}
|
||||||
${field.serialize(use_buefy=True)|n}
|
</b-field>
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<div class="field-wrapper ${field.name}">
|
|
||||||
<div class="field-row">
|
|
||||||
<label for="${field.oid}">${field.title}</label>
|
|
||||||
<div class="field">
|
|
||||||
${field.serialize()|n}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form_innards()">
|
<%def name="render_form_innards()">
|
||||||
% if use_buefy:
|
|
||||||
${h.form(request.current_route_url(), **{'@submit': 'submit{}'.format(form.component_studly)})}
|
${h.form(request.current_route_url(), **{'@submit': 'submit{}'.format(form.component_studly)})}
|
||||||
% else:
|
|
||||||
${h.form(request.current_route_url(), class_='autodisable')}
|
|
||||||
% endif
|
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
@ -75,53 +31,33 @@
|
||||||
${render_deform_field(form, dform['notes'])}
|
${render_deform_field(form, dform['notes'])}
|
||||||
|
|
||||||
% for key, pform in six.iteritems(params_forms):
|
% for key, pform in six.iteritems(params_forms):
|
||||||
% if use_buefy:
|
<div v-show="field_model_batch_type == '${key}'">
|
||||||
<div v-show="field_model_batch_type == '${key}'">
|
% for field in pform.make_deform_form():
|
||||||
% for field in pform.make_deform_form():
|
${render_deform_field(pform, field)}
|
||||||
${render_deform_field(pform, field)}
|
% endfor
|
||||||
% endfor
|
</div>
|
||||||
</div>
|
|
||||||
% else:
|
|
||||||
<div class="params-wrapper ${key}">
|
|
||||||
## TODO: hacky to use deform? at least is explicit..
|
|
||||||
% for field in pform.make_deform_form():
|
|
||||||
${render_deform_field(pform, field)}
|
|
||||||
% endfor
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endfor
|
% endfor
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
% if use_buefy:
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
native-type="submit"
|
||||||
native-type="submit"
|
:disabled="${form.component_studly}Submitting">
|
||||||
:disabled="${form.component_studly}Submitting">
|
{{ ${form.component_studly}ButtonText }}
|
||||||
{{ ${form.component_studly}ButtonText }}
|
</b-button>
|
||||||
</b-button>
|
<b-button tag="a" href="${url('products')}">
|
||||||
<b-button tag="a" href="${url('products')}">
|
Cancel
|
||||||
Cancel
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.submit('make-batch', "Create Batch")}
|
|
||||||
${h.link_to("Cancel", url('products'), class_='button')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form()">
|
<%def name="render_form()">
|
||||||
% if use_buefy:
|
<script type="text/x-template" id="${form.component}-template">
|
||||||
<script type="text/x-template" id="${form.component}-template">
|
${self.render_form_innards()}
|
||||||
${self.render_form_innards()}
|
</script>
|
||||||
</script>
|
|
||||||
% else:
|
|
||||||
<div class="form">
|
|
||||||
${self.render_form_innards()}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
|
|
|
@ -1,133 +1,26 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/index.mako" />
|
<%inherit file="/master/index.mako" />
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
|
||||||
${parent.extra_styles()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<style type="text/css">
|
|
||||||
|
|
||||||
table.label-printing th {
|
|
||||||
font-weight: normal;
|
|
||||||
padding: 0px 0px 2px 4px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.label-printing td {
|
|
||||||
padding: 0px 0px 0px 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.label-printing #label-quantity {
|
|
||||||
text-align: right;
|
|
||||||
width: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.grid table tbody td.size,
|
|
||||||
div.grid table tbody td.regular_price_uuid,
|
|
||||||
div.grid table tbody td.current_price_uuid {
|
|
||||||
padding-right: 6px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.grid table tbody td.labels {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy and label_profiles and master.has_perm('print_labels'):
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('.grid-wrapper .grid-header .tools select').selectmenu();
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('click', 'a.print_label', function() {
|
|
||||||
var tr = $(this).parents('tr:first');
|
|
||||||
var quantity = $('table.label-printing #label-quantity');
|
|
||||||
if (isNaN(quantity.val())) {
|
|
||||||
alert("You must provide a valid label quantity.");
|
|
||||||
quantity.select();
|
|
||||||
quantity.focus();
|
|
||||||
} else {
|
|
||||||
quantity = quantity.val();
|
|
||||||
|
|
||||||
var threshold = ${json.dumps(quick_label_speedbump_threshold)|n};
|
|
||||||
if (threshold && parseInt(quantity) >= threshold) {
|
|
||||||
if (!confirm("Are you sure you want to print " + quantity + " labels?")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = {
|
|
||||||
product: tr.data('uuid'),
|
|
||||||
profile: $('#label-profile').val(),
|
|
||||||
quantity: quantity
|
|
||||||
};
|
|
||||||
$.get('${url('products.print_labels')}', data, function(data) {
|
|
||||||
if (data.error) {
|
|
||||||
alert("An error occurred while attempting to print:\n\n" + data.error);
|
|
||||||
} else if (quantity == '1') {
|
|
||||||
alert("1 label has been printed.");
|
|
||||||
} else {
|
|
||||||
alert(quantity + " labels have been printed.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="grid_tools()">
|
<%def name="grid_tools()">
|
||||||
${parent.grid_tools()}
|
${parent.grid_tools()}
|
||||||
% if label_profiles and master.has_perm('print_labels'):
|
% if label_profiles and master.has_perm('print_labels'):
|
||||||
% if use_buefy:
|
<b-field grouped>
|
||||||
<b-field grouped>
|
<b-field label="Label">
|
||||||
<b-field label="Label">
|
<b-select v-model="quickLabelProfile">
|
||||||
<b-select v-model="quickLabelProfile">
|
% for profile in label_profiles:
|
||||||
% for profile in label_profiles:
|
<option value="${profile.uuid}">
|
||||||
<option value="${profile.uuid}">
|
${profile.description}
|
||||||
${profile.description}
|
</option>
|
||||||
</option>
|
% endfor
|
||||||
% endfor
|
</b-select>
|
||||||
</b-select>
|
</b-field>
|
||||||
</b-field>
|
<b-field label="Qty.">
|
||||||
<b-field label="Qty.">
|
<b-input v-model="quickLabelQuantity"
|
||||||
<b-input v-model="quickLabelQuantity"
|
ref="quickLabelQuantityInput"
|
||||||
ref="quickLabelQuantityInput"
|
style="width: 4rem;">
|
||||||
style="width: 4rem;">
|
</b-input>
|
||||||
</b-input>
|
</b-field>
|
||||||
</b-field>
|
</b-field>
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<table class="label-printing">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Label</th>
|
|
||||||
<th>Qty.</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<td>
|
|
||||||
<select name="label-profile" id="label-profile">
|
|
||||||
% for profile in label_profiles:
|
|
||||||
<option value="${profile.uuid}">${profile.description}</option>
|
|
||||||
% endfor
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" name="label-quantity" id="label-quantity" value="1" />
|
|
||||||
</td>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
|
@ -1,94 +1,16 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy and request.rattail_config.versioning_enabled() and master.has_perm('versions'):
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function showPriceHistory(typ) {
|
|
||||||
var dialog = $('#' + typ + '-price-history-dialog');
|
|
||||||
dialog.dialog({
|
|
||||||
title: typ[0].toUpperCase() + typ.slice(1) + " Price History",
|
|
||||||
width: 600,
|
|
||||||
height: 300,
|
|
||||||
modal: true,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "Close",
|
|
||||||
click: function() {
|
|
||||||
dialog.dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showCostHistory() {
|
|
||||||
var dialog = $('#cost-history-dialog');
|
|
||||||
dialog.dialog({
|
|
||||||
title: "Cost History",
|
|
||||||
width: 600,
|
|
||||||
height: 300,
|
|
||||||
modal: true,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "Close",
|
|
||||||
click: function() {
|
|
||||||
dialog.dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#view-regular-price-history').on('click', function() {
|
|
||||||
showPriceHistory('regular');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#view-current-price-history').on('click', function() {
|
|
||||||
showPriceHistory('current');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#view-suggested-price-history').on('click', function() {
|
|
||||||
showPriceHistory('suggested');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#view-cost-history').on('click', function() {
|
|
||||||
showCostHistory();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
% if use_buefy:
|
#main-product-panel {
|
||||||
#main-product-panel {
|
margin-right: 2em;
|
||||||
margin-right: 2em;
|
margin-top: 1em;
|
||||||
margin-top: 1em;
|
}
|
||||||
}
|
#pricing-panel .field-wrapper .field {
|
||||||
#pricing-panel .field-wrapper .field {
|
white-space: nowrap;
|
||||||
white-space: nowrap;
|
}
|
||||||
}
|
|
||||||
% else:
|
|
||||||
.price-history-dialog {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.price-history-dialog .grid {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
</style>
|
</style>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -100,37 +22,22 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="left_column()">
|
<%def name="left_column()">
|
||||||
% if use_buefy:
|
<nav class="panel" id="pricing-panel">
|
||||||
<nav class="panel" id="pricing-panel">
|
<p class="panel-heading">Pricing</p>
|
||||||
<p class="panel-heading">Pricing</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
<div>
|
||||||
<div>
|
${self.render_price_fields(form)}
|
||||||
${self.render_price_fields(form)}
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<nav class="panel">
|
|
||||||
<p class="panel-heading">Flags</p>
|
|
||||||
<div class="panel-block">
|
|
||||||
<div>
|
|
||||||
${self.render_flag_fields(form)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel">
|
|
||||||
<h2>Pricing</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
${self.render_price_fields(form)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
<div class="panel">
|
<nav class="panel">
|
||||||
<h2>Flags</h2>
|
<p class="panel-heading">Flags</p>
|
||||||
<div class="panel-body">
|
<div class="panel-block">
|
||||||
${self.render_flag_fields(form)}
|
<div>
|
||||||
|
${self.render_flag_fields(form)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
% endif
|
|
||||||
${self.extra_left_panels()}
|
${self.extra_left_panels()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -147,23 +54,14 @@
|
||||||
<%def name="extra_main_fields(form)"></%def>
|
<%def name="extra_main_fields(form)"></%def>
|
||||||
|
|
||||||
<%def name="organization_panel()">
|
<%def name="organization_panel()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Organization</p>
|
||||||
<p class="panel-heading">Organization</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
<div>
|
||||||
<div>
|
${self.render_organization_fields(form)}
|
||||||
${self.render_organization_fields(form)}
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel">
|
|
||||||
<h2>Organization</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
${self.render_organization_fields(form)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_organization_fields(form)">
|
<%def name="render_organization_fields(form)">
|
||||||
|
@ -195,23 +93,14 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="movement_panel()">
|
<%def name="movement_panel()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Movement</p>
|
||||||
<p class="panel-heading">Movement</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
<div>
|
||||||
<div>
|
${self.render_movement_fields(form)}
|
||||||
${self.render_movement_fields(form)}
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel">
|
|
||||||
<h2>Movement</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
${self.render_movement_fields(form)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_movement_fields(form)">
|
<%def name="render_movement_fields(form)">
|
||||||
|
@ -219,9 +108,7 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="lookup_codes_grid()">
|
<%def name="lookup_codes_grid()">
|
||||||
% if use_buefy:
|
${lookup_codes['grid'].render_buefy_table_element(data_prop='lookupCodesData')|n}
|
||||||
${lookup_codes['grid'].render_buefy_table_element(data_prop='lookupCodesData')|n}
|
|
||||||
% else:
|
|
||||||
<div class="grid full no-border">
|
<div class="grid full no-border">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -238,29 +125,19 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="lookup_codes_panel()">
|
<%def name="lookup_codes_panel()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Additional Lookup Codes</p>
|
||||||
<p class="panel-heading">Additional Lookup Codes</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
${self.lookup_codes_grid()}
|
||||||
${self.lookup_codes_grid()}
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel-grid" id="product-codes">
|
|
||||||
<h2>Additional Lookup Codes</h2>
|
|
||||||
${self.lookup_codes_grid()}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="sources_grid()">
|
<%def name="sources_grid()">
|
||||||
% if use_buefy:
|
${vendor_sources['grid'].render_buefy_table_element(data_prop='vendorSourcesData')|n}
|
||||||
${vendor_sources['grid'].render_buefy_table_element(data_prop='vendorSourcesData')|n}
|
|
||||||
% else:
|
|
||||||
<div class="grid full no-border">
|
<div class="grid full no-border">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -293,71 +170,40 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="sources_panel()">
|
<%def name="sources_panel()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">
|
||||||
<p class="panel-heading">
|
|
||||||
Vendor Sources
|
|
||||||
% if request.rattail_config.versioning_enabled() and master.has_perm('versions'):
|
|
||||||
<a href="#" @click.prevent="showCostHistory()">
|
|
||||||
(view cost history)
|
|
||||||
</a>
|
|
||||||
% endif
|
|
||||||
</p>
|
|
||||||
<div class="panel-block">
|
|
||||||
${self.sources_grid()}
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel-grid" id="product-costs">
|
|
||||||
<h2>
|
|
||||||
Vendor Sources
|
Vendor Sources
|
||||||
% if request.rattail_config.versioning_enabled() and master.has_perm('versions'):
|
% if request.rattail_config.versioning_enabled() and master.has_perm('versions'):
|
||||||
<a id="view-cost-history" href="#">(view cost history)</a>
|
<a href="#" @click.prevent="showCostHistory()">
|
||||||
|
(view cost history)
|
||||||
|
</a>
|
||||||
% endif
|
% endif
|
||||||
</h2>
|
</p>
|
||||||
${self.sources_grid()}
|
<div class="panel-block">
|
||||||
</div>
|
${self.sources_grid()}
|
||||||
% endif
|
</div>
|
||||||
|
</nav>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="notes_panel()">
|
<%def name="notes_panel()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Notes</p>
|
||||||
<p class="panel-heading">Notes</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
|
||||||
<div class="field">${form.render_field_readonly('notes')}</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel">
|
|
||||||
<h2>Notes</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div class="field">${form.render_field_readonly('notes')}</div>
|
<div class="field">${form.render_field_readonly('notes')}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="ingredients_panel()">
|
<%def name="ingredients_panel()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Ingredients</p>
|
||||||
<p class="panel-heading">Ingredients</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
|
||||||
${form.render_field_readonly('ingredients')}
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel">
|
|
||||||
<h2>Ingredients</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
${form.render_field_readonly('ingredients')}
|
${form.render_field_readonly('ingredients')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_left_panels()"></%def>
|
<%def name="extra_left_panels()"></%def>
|
||||||
|
@ -366,7 +212,7 @@
|
||||||
|
|
||||||
<%def name="render_this_page()">
|
<%def name="render_this_page()">
|
||||||
${parent.render_this_page()}
|
${parent.render_this_page()}
|
||||||
% if use_buefy and request.rattail_config.versioning_enabled() and master.has_perm('versions'):
|
% if request.rattail_config.versioning_enabled() and master.has_perm('versions'):
|
||||||
|
|
||||||
<b-modal :active.sync="showingPriceHistory_regular"
|
<b-modal :active.sync="showingPriceHistory_regular"
|
||||||
has-modal-card>
|
has-modal-card>
|
||||||
|
@ -447,83 +293,34 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
% if use_buefy:
|
|
||||||
<div style="display: flex; flex-direction: column;">
|
<div style="display: flex; flex-direction: column;">
|
||||||
|
|
||||||
<nav class="panel" id="main-product-panel">
|
<nav class="panel" id="main-product-panel">
|
||||||
<p class="panel-heading">Product</p>
|
<p class="panel-heading">Product</p>
|
||||||
<div class="panel-block">
|
<div class="panel-block">
|
||||||
<div style="display: flex; justify-content: space-between; width: 100%;">
|
<div style="display: flex; justify-content: space-between; width: 100%;">
|
||||||
<div>
|
<div>
|
||||||
${self.render_main_fields(form)}
|
${self.render_main_fields(form)}
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
% if image_url:
|
|
||||||
${h.image(image_url, "Product Image", id='product-image', width=150, height=150)}
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div style="display: flex;">
|
|
||||||
<div class="panel-wrapper"> <!-- left column -->
|
|
||||||
${self.left_column()}
|
|
||||||
</div> <!-- left column -->
|
|
||||||
<div class="panel-wrapper" style="margin-left: 1em;"> <!-- right column -->
|
|
||||||
${self.right_column()}
|
|
||||||
</div> <!-- right column -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
% else:
|
% if image_url:
|
||||||
## legacy / not buefy
|
${h.image(image_url, "Product Image", id='product-image', width=150, height=150)}
|
||||||
|
% endif
|
||||||
<div style="display: flex; flex-direction: column;">
|
|
||||||
|
|
||||||
<div class="panel" id="product-main">
|
|
||||||
<h2>Product</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div style="display: flex; justify-content: space-between;">
|
|
||||||
<div>
|
|
||||||
${self.render_main_fields(form)}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
% if image_url:
|
|
||||||
${h.image(image_url, "Product Image", id='product-image', width=150, height=150)}
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex;">
|
|
||||||
<div class="panel-wrapper"> <!-- left column -->
|
|
||||||
${self.left_column()}
|
|
||||||
</div> <!-- left column -->
|
|
||||||
<div class="panel-wrapper" style="margin-left: 1em;"> <!-- right column -->
|
|
||||||
${self.right_column()}
|
|
||||||
</div> <!-- right column -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
% if request.rattail_config.versioning_enabled() and master.has_perm('versions'):
|
<div style="display: flex;">
|
||||||
<div class="price-history-dialog" id="regular-price-history-dialog">
|
<div class="panel-wrapper"> <!-- left column -->
|
||||||
${regular_price_history_grid.render_grid()|n}
|
${self.left_column()}
|
||||||
</div>
|
</div> <!-- left column -->
|
||||||
<div class="price-history-dialog" id="current-price-history-dialog">
|
<div class="panel-wrapper" style="margin-left: 1em;"> <!-- right column -->
|
||||||
${current_price_history_grid.render_grid()|n}
|
${self.right_column()}
|
||||||
</div>
|
</div> <!-- right column -->
|
||||||
<div class="price-history-dialog" id="suggested-price-history-dialog">
|
</div>
|
||||||
${suggested_price_history_grid.render_grid()|n}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="price-history-dialog" id="cost-history-dialog">
|
|
||||||
${cost_history_grid.render_grid()|n}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if buttons:
|
% if buttons:
|
||||||
${buttons|n}
|
${buttons|n}
|
||||||
|
|
|
@ -1,468 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/base.mako" />
|
|
||||||
|
|
||||||
<%def name="title()">Receiving Form (${batch.vendor})</%def>
|
|
||||||
|
|
||||||
<%def name="head_tags()">
|
|
||||||
${parent.head_tags()}
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/numeric.js'))}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function assert_quantity() {
|
|
||||||
if ($('#cases').val() && parseFloat($('#cases').val())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ($('#units').val() && parseFloat($('#units').val())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
alert("Please provide case and/or unit quantity");
|
|
||||||
$('#cases').select().focus();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function invalid_product(msg) {
|
|
||||||
$('#received-product-info p').text(msg);
|
|
||||||
$('#received-product-info img').hide();
|
|
||||||
$('#upc').focus().select();
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', true);
|
|
||||||
$('.field-wrapper.units input').prop('disabled', true);
|
|
||||||
$('.buttons button').button('disable');
|
|
||||||
}
|
|
||||||
|
|
||||||
function pretty_quantity(cases, units) {
|
|
||||||
if (cases && units) {
|
|
||||||
return cases + " cases, " + units + " units";
|
|
||||||
} else if (cases) {
|
|
||||||
return cases + " cases";
|
|
||||||
} else if (units) {
|
|
||||||
return units + " units";
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function show_quantity(name, cases, units) {
|
|
||||||
var quantity = pretty_quantity(cases, units);
|
|
||||||
var field = $('.field-wrapper.quantity_' + name);
|
|
||||||
field.find('.field').text(quantity);
|
|
||||||
if (quantity || name == 'ordered') {
|
|
||||||
field.show();
|
|
||||||
} else {
|
|
||||||
field.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('#upc').keydown(function(event) {
|
|
||||||
|
|
||||||
if (key_allowed(event)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (key_modifies(event)) {
|
|
||||||
$('#product').val('');
|
|
||||||
$('#received-product-info p').html("please ENTER a scancode");
|
|
||||||
$('#received-product-info img').hide();
|
|
||||||
$('#received-product-info .warning').hide();
|
|
||||||
$('.product-fields').hide();
|
|
||||||
$('.receiving-fields').hide();
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', true);
|
|
||||||
$('.field-wrapper.units input').prop('disabled', true);
|
|
||||||
$('.buttons button').button('disable');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// when user presses ENTER, do product lookup
|
|
||||||
if (event.which == 13) {
|
|
||||||
var upc = $(this).val();
|
|
||||||
var data = {'upc': upc};
|
|
||||||
$.get('${url('purchases.batch.receiving_lookup', uuid=batch.uuid)}', data, function(data) {
|
|
||||||
|
|
||||||
if (data.error) {
|
|
||||||
alert(data.error);
|
|
||||||
if (data.redirect) {
|
|
||||||
$('#receiving-form').mask("Redirecting...");
|
|
||||||
location.href = data.redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (data.product) {
|
|
||||||
$('#upc').val(data.product.upc_pretty);
|
|
||||||
$('#product').val(data.product.uuid);
|
|
||||||
$('#brand_name').val(data.product.brand_name);
|
|
||||||
$('#description').val(data.product.description);
|
|
||||||
$('#size').val(data.product.size);
|
|
||||||
$('#case_quantity').val(data.product.case_quantity);
|
|
||||||
|
|
||||||
$('#received-product-info p').text(data.product.full_description);
|
|
||||||
$('#received-product-info img').attr('src', data.product.image_url).show();
|
|
||||||
if (! data.product.uuid) {
|
|
||||||
// $('#received-product-info .warning.notfound').show();
|
|
||||||
$('.product-fields').show();
|
|
||||||
}
|
|
||||||
if (data.product.found_in_batch) {
|
|
||||||
show_quantity('ordered', data.product.cases_ordered, data.product.units_ordered);
|
|
||||||
show_quantity('received', data.product.cases_received, data.product.units_received);
|
|
||||||
show_quantity('damaged', data.product.cases_damaged, data.product.units_damaged);
|
|
||||||
show_quantity('expired', data.product.cases_expired, data.product.units_expired);
|
|
||||||
show_quantity('mispick', data.product.cases_mispick, data.product.units_mispick);
|
|
||||||
$('.receiving-fields').show();
|
|
||||||
} else {
|
|
||||||
$('#received-product-info .warning.notordered').show();
|
|
||||||
}
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', false);
|
|
||||||
$('.field-wrapper.units input').prop('disabled', false);
|
|
||||||
$('.buttons button').button('enable');
|
|
||||||
$('#cases').focus().select();
|
|
||||||
|
|
||||||
} else if (data.upc) {
|
|
||||||
$('#upc').val(data.upc_pretty);
|
|
||||||
$('#received-product-info p').text("product not found in our system");
|
|
||||||
$('#received-product-info img').attr('src', data.image_url).show();
|
|
||||||
|
|
||||||
$('#product').val('');
|
|
||||||
$('#brand_name').val('');
|
|
||||||
$('#description').val('');
|
|
||||||
$('#size').val('');
|
|
||||||
$('#case_quantity').val('');
|
|
||||||
|
|
||||||
$('#received-product-info .warning.notfound').show();
|
|
||||||
$('.product-fields').show();
|
|
||||||
$('#brand_name').focus();
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', false);
|
|
||||||
$('.field-wrapper.units input').prop('disabled', false);
|
|
||||||
$('.buttons button').button('enable');
|
|
||||||
|
|
||||||
} else {
|
|
||||||
invalid_product('product not found');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#received').click(function() {
|
|
||||||
if (! assert_quantity()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$(this).button('disable').button('option', 'label', "Working...");
|
|
||||||
$('#mode').val('received');
|
|
||||||
$('#receiving-form').submit();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#damaged').click(function() {
|
|
||||||
if (! assert_quantity()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$(this).button('disable').button('option', 'label', "Working...");
|
|
||||||
$('#mode').val('damaged');
|
|
||||||
$('#damaged-dialog').dialog({
|
|
||||||
title: "Damaged Product",
|
|
||||||
modal: true,
|
|
||||||
width: '500px',
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "OK",
|
|
||||||
click: function() {
|
|
||||||
$('#damaged-dialog').dialog('close');
|
|
||||||
$('#receiving-form #trash').val($('#damaged-dialog #trash').is(':checked') ? '1' : '');
|
|
||||||
$('#receiving-form').submit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
click: function() {
|
|
||||||
$('#damaged').button('option', 'label', "Damaged").button('enable');
|
|
||||||
$('#damaged-dialog').dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#expiration input[type="date"]').datepicker();
|
|
||||||
|
|
||||||
$('#expired').click(function() {
|
|
||||||
if (! assert_quantity()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$(this).button('disable').button('option', 'label', "Working...");
|
|
||||||
$('#mode').val('expired');
|
|
||||||
$('#expiration').dialog({
|
|
||||||
title: "Expired / Short Date",
|
|
||||||
modal: true,
|
|
||||||
width: '500px',
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "OK",
|
|
||||||
click: function() {
|
|
||||||
$('#expiration').dialog('close');
|
|
||||||
$('#receiving-form #expiration_date').val(
|
|
||||||
$('#expiration input[type="date"]').val());
|
|
||||||
$('#receiving-form #trash').val($('#expiration #trash').is(':checked') ? '1' : '');
|
|
||||||
$('#receiving-form').submit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
click: function() {
|
|
||||||
$('#expired').button('option', 'label', "Expired").button('enable');
|
|
||||||
$('#expiration').dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#mispick').click(function() {
|
|
||||||
if (! assert_quantity()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$(this).button('disable').button('option', 'label', "Working...");
|
|
||||||
$('#ordered-product').val('');
|
|
||||||
$('#ordered-product-textbox').val('');
|
|
||||||
$('#ordered-product-info p').html("please ENTER a scancode");
|
|
||||||
$('#ordered-product-info img').hide();
|
|
||||||
$('#mispick-dialog').dialog({
|
|
||||||
title: "Mispick - Ordered Product",
|
|
||||||
modal: true,
|
|
||||||
width: 400,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "OK",
|
|
||||||
click: function() {
|
|
||||||
if ($('#ordered-product-info .warning').is(':visible')) {
|
|
||||||
alert("You must choose a product which was ordered.");
|
|
||||||
$('#ordered-product-textbox').select().focus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$('#mispick-dialog').dialog('close');
|
|
||||||
$('#mode').val('mispick');
|
|
||||||
$('#receiving-form').submit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
click: function() {
|
|
||||||
$('#mispick').button('option', 'label', "Mispick").button('enable');
|
|
||||||
$('#mispick-dialog').dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#ordered-product-textbox').keydown(function(event) {
|
|
||||||
|
|
||||||
if (key_allowed(event)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (key_modifies(event)) {
|
|
||||||
$('#ordered_product').val('');
|
|
||||||
$('#ordered-product-info p').html("please ENTER a scancode");
|
|
||||||
$('#ordered-product-info img').hide();
|
|
||||||
$('#ordered-product-info .warning').hide();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (event.which == 13) {
|
|
||||||
var input = $(this);
|
|
||||||
var data = {upc: input.val()};
|
|
||||||
$.get('${url('purchases.batch.receiving_lookup', uuid=batch.uuid)}', data, function(data) {
|
|
||||||
if (data.error) {
|
|
||||||
alert(data.error);
|
|
||||||
if (data.redirect) {
|
|
||||||
$('#mispick-dialog').mask("Redirecting...");
|
|
||||||
location.href = data.redirect;
|
|
||||||
}
|
|
||||||
} else if (data.product) {
|
|
||||||
input.val(data.product.upc_pretty);
|
|
||||||
$('#ordered_product').val(data.product.uuid);
|
|
||||||
$('#ordered-product-info p').text(data.product.full_description);
|
|
||||||
$('#ordered-product-info img').attr('src', data.product.image_url).show();
|
|
||||||
if (data.product.found_in_batch) {
|
|
||||||
$('#ordered-product-info .warning').hide();
|
|
||||||
} else {
|
|
||||||
$('#ordered-product-info .warning').show();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$('#ordered-product-info p').text("product not found");
|
|
||||||
$('#ordered-product-info img').hide();
|
|
||||||
$('#ordered-product-info .warning').hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#receiving-form').submit(function() {
|
|
||||||
$(this).mask("Working...");
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#upc').focus();
|
|
||||||
$('.field-wrapper.cases input').prop('disabled', true);
|
|
||||||
$('.field-wrapper.units input').prop('disabled', true);
|
|
||||||
$('.buttons button').button('disable');
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
|
||||||
${parent.extra_styles()}
|
|
||||||
<style type="text/css">
|
|
||||||
|
|
||||||
.product-info {
|
|
||||||
margin-top: 0.5em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-info p {
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.product-info .img-wrapper {
|
|
||||||
height: 150px;
|
|
||||||
margin: 0.5em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#received-product-info .warning {
|
|
||||||
background: #f66;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mispick-dialog input[type="text"],
|
|
||||||
#ordered-product-info {
|
|
||||||
width: 320px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ordered-product-info .warning {
|
|
||||||
background: #f66;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
|
||||||
<li>${h.link_to("Back to Purchase Batch", url('purchases.batch.view', uuid=batch.uuid))}</li>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
|
|
||||||
<ul id="context-menu">
|
|
||||||
${self.context_menu_items()}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div class="form-wrapper">
|
|
||||||
${form.begin(id='receiving-form')}
|
|
||||||
${form.csrf_token()}
|
|
||||||
${h.hidden('mode')}
|
|
||||||
${h.hidden('expiration_date')}
|
|
||||||
${h.hidden('trash')}
|
|
||||||
${h.hidden('ordered_product')}
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label for="upc">Receiving UPC</label>
|
|
||||||
<div class="field">
|
|
||||||
${h.hidden('product')}
|
|
||||||
<div>${h.text('upc', autocomplete='off')}</div>
|
|
||||||
<div id="received-product-info" class="product-info">
|
|
||||||
<p>please ENTER a scancode</p>
|
|
||||||
<div class="img-wrapper"><img /></div>
|
|
||||||
<div class="warning notfound">please confirm UPC and provide more details</div>
|
|
||||||
<div class="warning notordered">warning: product not found on current purchase</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="product-fields" style="display: none;">
|
|
||||||
|
|
||||||
<div class="field-wrapper brand_name">
|
|
||||||
<label for="brand_name">Brand Name</label>
|
|
||||||
<div class="field">${h.text('brand_name')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper description">
|
|
||||||
<label for="description">Description</label>
|
|
||||||
<div class="field">${h.text('description')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper size">
|
|
||||||
<label for="size">Size</label>
|
|
||||||
<div class="field">${h.text('size')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper case_quantity">
|
|
||||||
<label for="case_quantity">Units in Case</label>
|
|
||||||
<div class="field">${h.text('case_quantity')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="receiving-fields" style="display: none;">
|
|
||||||
|
|
||||||
<div class="field-wrapper quantity_ordered">
|
|
||||||
<label for="quantity_ordered">Ordered</label>
|
|
||||||
<div class="field"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper quantity_received">
|
|
||||||
<label for="quantity_received">Received</label>
|
|
||||||
<div class="field"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper quantity_damaged">
|
|
||||||
<label for="quantity_damaged">Damaged</label>
|
|
||||||
<div class="field"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper quantity_expired">
|
|
||||||
<label for="quantity_expired">Expired</label>
|
|
||||||
<div class="field"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper quantity_mispick">
|
|
||||||
<label for="quantity_mispick">Mispick</label>
|
|
||||||
<div class="field"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper cases">
|
|
||||||
<label for="cases">Cases</label>
|
|
||||||
<div class="field">${h.text('cases', autocomplete='off')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper units">
|
|
||||||
<label for="units">Units</label>
|
|
||||||
<div class="field">${h.text('units', autocomplete='off')}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
<button type="button" id="received">Received</button>
|
|
||||||
<button type="button" id="damaged">Damaged</button>
|
|
||||||
<button type="button" id="expired">Expired</button>
|
|
||||||
<!-- <button type="button" id="mispick">Mispick</button> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${form.end()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="damaged-dialog" style="display: none;">
|
|
||||||
<div class="field-wrapper trash">${h.checkbox('trash', label="Product will be discarded and cannot be returned", checked=False)}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="expiration" style="display: none;">
|
|
||||||
<div class="field-wrapper expiration-date">
|
|
||||||
<label for="expiration-date">Expiration Date</label>
|
|
||||||
<div class="field">${h.text('expiration-date', type='date')}</div>
|
|
||||||
</div>
|
|
||||||
<div class="field-wrapper trash">${h.checkbox('trash', label="Product will be discarded and cannot be returned", checked=False)}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="mispick-dialog" style="display: none;">
|
|
||||||
<div>${h.text('ordered-product-textbox', autocomplete='off')}</div>
|
|
||||||
<div id="ordered-product-info" class="product-info">
|
|
||||||
<p>please ENTER a scancode</p>
|
|
||||||
<div class="img-wrapper"><img /></div>
|
|
||||||
<div class="warning">warning: product not found on current purchase</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,80 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/batch/create.mako" />
|
<%inherit file="/batch/create.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
## TODO: deprecate / remove this
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${self.func_show_batch_type()}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
% if master.handler.allow_truck_dump_receiving():
|
|
||||||
var batch_vendor_map = ${json.dumps(batch_vendor_map)|n};
|
|
||||||
% endif
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
$('.batch_type select').on('selectmenuchange', function(event, ui) {
|
|
||||||
show_batch_type(ui.item.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.truck_dump_batch_uuid select').on('selectmenuchange', function(event, ui) {
|
|
||||||
var form = $(this).parents('form');
|
|
||||||
var uuid = ui.item.value ? batch_vendor_map[ui.item.value] : '';
|
|
||||||
form.find('input[name="vendor_uuid"]').val(uuid);
|
|
||||||
});
|
|
||||||
|
|
||||||
show_batch_type();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="func_show_batch_type()">
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function show_batch_type(batch_type) {
|
|
||||||
|
|
||||||
if (batch_type === undefined) {
|
|
||||||
batch_type = $('.field-wrapper.batch_type select').val();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (batch_type == 'from_scratch') {
|
|
||||||
$('.field-wrapper.truck_dump_batch_uuid').hide();
|
|
||||||
$('.field-wrapper.invoice_file').hide();
|
|
||||||
$('.field-wrapper.invoice_parser_key').hide();
|
|
||||||
$('.field-wrapper.vendor_uuid').show();
|
|
||||||
$('.field-wrapper.date_ordered').show();
|
|
||||||
$('.field-wrapper.date_received').show();
|
|
||||||
$('.field-wrapper.po_number').show();
|
|
||||||
$('.field-wrapper.invoice_date').show();
|
|
||||||
$('.field-wrapper.invoice_number').show();
|
|
||||||
|
|
||||||
} else if (batch_type == 'truck_dump_children_first') {
|
|
||||||
$('.field-wrapper.truck_dump_batch_uuid').hide();
|
|
||||||
$('.field-wrapper.invoice_file').hide();
|
|
||||||
$('.field-wrapper.invoice_parser_key').hide();
|
|
||||||
$('.field-wrapper.vendor_uuid').show();
|
|
||||||
$('.field-wrapper.date_ordered').hide();
|
|
||||||
$('.field-wrapper.date_received').show();
|
|
||||||
$('.field-wrapper.po_number').hide();
|
|
||||||
$('.field-wrapper.invoice_date').hide();
|
|
||||||
$('.field-wrapper.invoice_number').hide();
|
|
||||||
|
|
||||||
} else if (batch_type == 'truck_dump_children_last') {
|
|
||||||
$('.field-wrapper.truck_dump_batch_uuid').hide();
|
|
||||||
$('.field-wrapper.invoice_file').hide();
|
|
||||||
$('.field-wrapper.invoice_parser_key').hide();
|
|
||||||
$('.field-wrapper.vendor_uuid').show();
|
|
||||||
$('.field-wrapper.date_ordered').hide();
|
|
||||||
$('.field-wrapper.date_received').show();
|
|
||||||
$('.field-wrapper.po_number').hide();
|
|
||||||
$('.field-wrapper.invoice_date').hide();
|
|
||||||
$('.field-wrapper.invoice_number').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -11,35 +11,6 @@
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function toggleFields(creditType) {
|
|
||||||
if (creditType === undefined) {
|
|
||||||
creditType = $('select[name="credit_type"]').val();
|
|
||||||
}
|
|
||||||
if (creditType == 'expired') {
|
|
||||||
$('.field-wrapper.expiration_date').show();
|
|
||||||
} else {
|
|
||||||
$('.field-wrapper.expiration_date').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
toggleFields();
|
|
||||||
|
|
||||||
$('select[name="credit_type"]').on('selectmenuchange', function(event, ui) {
|
|
||||||
toggleFields(ui.item.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="render_buefy_form()">
|
<%def name="render_buefy_form()">
|
||||||
|
|
||||||
<p class="block">
|
<p class="block">
|
||||||
|
@ -75,30 +46,7 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form()">
|
<%def name="render_form()">
|
||||||
% if use_buefy:
|
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.buefy_form_body))|n}
|
||||||
|
|
||||||
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.buefy_form_body))|n}
|
|
||||||
|
|
||||||
% else:
|
|
||||||
|
|
||||||
<p style="padding: 1em;">
|
|
||||||
Please select the "state" of the product, and enter the appropriate
|
|
||||||
quantity.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p style="padding: 1em;">
|
|
||||||
Note that this tool will <strong>deduct</strong> from the "received"
|
|
||||||
quantity, and <strong>add</strong> to the corresponding credit quantity.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p style="padding: 1em;">
|
|
||||||
Please see ${h.link_to("Receive Row", url('{}.receive_row'.format(route_prefix), uuid=batch.uuid, row_uuid=row.uuid))}
|
|
||||||
if you need to "receive" instead of "convert" the product.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
${parent.render_form()}
|
|
||||||
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,35 +11,6 @@
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function toggleFields(mode) {
|
|
||||||
if (mode === undefined) {
|
|
||||||
mode = $('select[name="mode"]').val();
|
|
||||||
}
|
|
||||||
if (mode == 'expired') {
|
|
||||||
$('.field-wrapper.expiration_date').show();
|
|
||||||
} else {
|
|
||||||
$('.field-wrapper.expiration_date').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
toggleFields();
|
|
||||||
|
|
||||||
$('select[name="mode"]').on('selectmenuchange', function(event, ui) {
|
|
||||||
toggleFields(ui.item.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="render_buefy_form()">
|
<%def name="render_buefy_form()">
|
||||||
|
|
||||||
<p class="block">
|
<p class="block">
|
||||||
|
@ -72,30 +43,7 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form()">
|
<%def name="render_form()">
|
||||||
% if use_buefy:
|
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.buefy_form_body))|n}
|
||||||
|
|
||||||
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.buefy_form_body))|n}
|
|
||||||
|
|
||||||
% else:
|
|
||||||
|
|
||||||
<p style="padding: 1em;">
|
|
||||||
Please select the "state" of the product, and enter the appropriate
|
|
||||||
quantity.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p style="padding: 1em;">
|
|
||||||
Note that this tool will <strong>add</strong> the corresponding
|
|
||||||
quantities for the row.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p style="padding: 1em;">
|
|
||||||
Please see ${h.link_to("Declare Credit", url('{}.declare_credit'.format(route_prefix), uuid=batch.uuid, row_uuid=row.uuid))}
|
|
||||||
if you need to "convert" some already-received amount, into a credit.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
${parent.render_form()}
|
|
||||||
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,311 +1,32 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/batch/view.mako" />
|
<%inherit file="/batch/view.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy and master.has_perm('edit_row'):
|
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/numeric.js'))}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
% if not batch.executed:
|
|
||||||
// keep track of which cost value is currently being edited
|
|
||||||
var editing_catalog_cost = null;
|
|
||||||
var editing_invoice_cost = null;
|
|
||||||
|
|
||||||
function start_editing(td) {
|
|
||||||
var value = null;
|
|
||||||
var text = td.text().replace(/^\s+|\s+$/g, '');
|
|
||||||
if (text) {
|
|
||||||
td.data('previous-value', text);
|
|
||||||
td.text('');
|
|
||||||
value = parseFloat(text.replace('$', ''));
|
|
||||||
}
|
|
||||||
var input = $('<input type="text" />');
|
|
||||||
td.append(input);
|
|
||||||
value = value ? value.toString() : '';
|
|
||||||
input.val(value).select().focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
function start_editing_catalog_cost(td) {
|
|
||||||
start_editing(td);
|
|
||||||
editing_catalog_cost = td;
|
|
||||||
}
|
|
||||||
|
|
||||||
function start_editing_invoice_cost(td) {
|
|
||||||
start_editing(td);
|
|
||||||
editing_invoice_cost = td;
|
|
||||||
}
|
|
||||||
|
|
||||||
function start_editing_next_catalog_cost() {
|
|
||||||
var tr = editing_catalog_cost.parents('tr:first');
|
|
||||||
var next = tr.next('tr:first');
|
|
||||||
if (next.length) {
|
|
||||||
start_editing_catalog_cost(next.find('td.catalog_unit_cost'));
|
|
||||||
} else {
|
|
||||||
editing_catalog_cost = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function start_editing_next_invoice_cost() {
|
|
||||||
var tr = editing_invoice_cost.parents('tr:first');
|
|
||||||
var next = tr.next('tr:first');
|
|
||||||
if (next.length) {
|
|
||||||
start_editing_invoice_cost(next.find('td.invoice_unit_cost'));
|
|
||||||
} else {
|
|
||||||
editing_invoice_cost = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancel_edit(td) {
|
|
||||||
var input = td.find('input');
|
|
||||||
input.blur();
|
|
||||||
input.remove();
|
|
||||||
var value = td.data('previous-value');
|
|
||||||
if (value) {
|
|
||||||
td.text(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancel_edit_catalog_cost() {
|
|
||||||
cancel_edit(editing_catalog_cost);
|
|
||||||
editing_catalog_cost = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancel_edit_invoice_cost() {
|
|
||||||
cancel_edit(editing_invoice_cost);
|
|
||||||
editing_invoice_cost = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
% endif
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
% if not batch.executed:
|
|
||||||
$('.grid-wrapper').on('click', '.grid td.catalog_unit_cost', function() {
|
|
||||||
if (editing_catalog_cost) {
|
|
||||||
editing_catalog_cost.find('input').focus();
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (editing_invoice_cost) {
|
|
||||||
editing_invoice_cost.find('input').focus();
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var td = $(this);
|
|
||||||
start_editing_catalog_cost(td);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('click', '.grid td.invoice_unit_cost', function() {
|
|
||||||
if (editing_invoice_cost) {
|
|
||||||
editing_invoice_cost.find('input').focus();
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (editing_catalog_cost) {
|
|
||||||
editing_catalog_cost.find('input').focus();
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var td = $(this);
|
|
||||||
start_editing_invoice_cost(td);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('keyup', '.grid td.catalog_unit_cost input', function(event) {
|
|
||||||
var input = $(this);
|
|
||||||
|
|
||||||
// let numeric keys modify input value
|
|
||||||
if (! key_modifies(event)) {
|
|
||||||
|
|
||||||
// when user presses Enter while editing cost value, submit
|
|
||||||
// value to server for immediate persistence
|
|
||||||
if (event.which == 13) {
|
|
||||||
$('.grid-wrapper').mask("Updating cost...");
|
|
||||||
var url = '${url('receiving.update_row_cost', uuid=batch.uuid)}';
|
|
||||||
var td = input.parents('td:first');
|
|
||||||
var tr = td.parents('tr:first');
|
|
||||||
var data = {
|
|
||||||
'_csrf': $('[name="_csrf"]').val(),
|
|
||||||
'row_uuid': tr.data('uuid'),
|
|
||||||
'catalog_unit_cost': input.val()
|
|
||||||
};
|
|
||||||
$.post(url, data, function(data) {
|
|
||||||
if (data.error) {
|
|
||||||
alert(data.error);
|
|
||||||
} else {
|
|
||||||
var total = null;
|
|
||||||
|
|
||||||
// update catalog cost for row
|
|
||||||
td.text(data.row.catalog_unit_cost);
|
|
||||||
|
|
||||||
// mark cost as confirmed
|
|
||||||
if (data.row.catalog_cost_confirmed) {
|
|
||||||
tr.addClass('catalog_cost_confirmed');
|
|
||||||
}
|
|
||||||
|
|
||||||
input.blur();
|
|
||||||
input.remove();
|
|
||||||
start_editing_next_catalog_cost();
|
|
||||||
}
|
|
||||||
$('.grid-wrapper').unmask();
|
|
||||||
});
|
|
||||||
|
|
||||||
// When user presses Escape while editing totals, cancel the edit.
|
|
||||||
} else if (event.which == 27) {
|
|
||||||
cancel_edit_catalog_cost();
|
|
||||||
|
|
||||||
// Most other keys at this point should be unwanted...
|
|
||||||
} else if (! key_allowed(event)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('keyup', '.grid td.invoice_unit_cost input', function(event) {
|
|
||||||
var input = $(this);
|
|
||||||
|
|
||||||
// let numeric keys modify input value
|
|
||||||
if (! key_modifies(event)) {
|
|
||||||
|
|
||||||
// when user presses Enter while editing cost value, submit
|
|
||||||
// value to server for immediate persistence
|
|
||||||
if (event.which == 13) {
|
|
||||||
$('.grid-wrapper').mask("Updating cost...");
|
|
||||||
var url = '${url('receiving.update_row_cost', uuid=batch.uuid)}';
|
|
||||||
var td = input.parents('td:first');
|
|
||||||
var tr = td.parents('tr:first');
|
|
||||||
var data = {
|
|
||||||
'_csrf': $('[name="_csrf"]').val(),
|
|
||||||
'row_uuid': tr.data('uuid'),
|
|
||||||
'invoice_unit_cost': input.val()
|
|
||||||
};
|
|
||||||
$.post(url, data, function(data) {
|
|
||||||
if (data.error) {
|
|
||||||
alert(data.error);
|
|
||||||
} else {
|
|
||||||
var total = null;
|
|
||||||
|
|
||||||
// update unit cost for row
|
|
||||||
td.text(data.row.invoice_unit_cost);
|
|
||||||
|
|
||||||
// update invoice total for row
|
|
||||||
total = tr.find('td.invoice_total_calculated');
|
|
||||||
total.text('$' + data.row.invoice_total_calculated);
|
|
||||||
|
|
||||||
// update invoice total for batch
|
|
||||||
total = $('.form .field-wrapper.invoice_total_calculated .field');
|
|
||||||
total.text('$' + data.batch.invoice_total_calculated);
|
|
||||||
|
|
||||||
// mark cost as confirmed
|
|
||||||
if (data.row.invoice_cost_confirmed) {
|
|
||||||
tr.addClass('invoice_cost_confirmed');
|
|
||||||
}
|
|
||||||
|
|
||||||
input.blur();
|
|
||||||
input.remove();
|
|
||||||
start_editing_next_invoice_cost();
|
|
||||||
}
|
|
||||||
$('.grid-wrapper').unmask();
|
|
||||||
});
|
|
||||||
|
|
||||||
// When user presses Escape while editing totals, cancel the edit.
|
|
||||||
} else if (event.which == 27) {
|
|
||||||
cancel_edit_invoice_cost();
|
|
||||||
|
|
||||||
// Most other keys at this point should be unwanted...
|
|
||||||
} else if (! key_allowed(event)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
|
|
||||||
$('.grid-wrapper').on('click', '.grid .actions a.transform', function() {
|
|
||||||
|
|
||||||
var form = $('form[name="transform-unit-form"]');
|
|
||||||
var row_uuid = $(this).parents('tr:first').data('uuid');
|
|
||||||
form.find('[name="row_uuid"]').val(row_uuid);
|
|
||||||
|
|
||||||
$.get(form.attr('action'), {row_uuid: row_uuid}, function(data) {
|
|
||||||
|
|
||||||
if (typeof(data) == 'object') {
|
|
||||||
alert(data.error);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$('#transform-unit-dialog').html(data);
|
|
||||||
$('#transform-unit-dialog').dialog({
|
|
||||||
title: "Transform Pack to Unit Item",
|
|
||||||
width: 800,
|
|
||||||
height: 450,
|
|
||||||
modal: true,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
text: "Transform",
|
|
||||||
click: function(event) {
|
|
||||||
disable_button(dialog_button(event));
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Cancel",
|
|
||||||
click: function() {
|
|
||||||
$(this).dialog('close');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if use_buefy:
|
<style type="text/css">
|
||||||
<style type="text/css">
|
% if allow_edit_catalog_unit_cost:
|
||||||
% if allow_edit_catalog_unit_cost:
|
td.c_catalog_unit_cost {
|
||||||
td.c_catalog_unit_cost {
|
cursor: pointer;
|
||||||
cursor: pointer;
|
background-color: #fcc;
|
||||||
background-color: #fcc;
|
|
||||||
}
|
|
||||||
tr.catalog_cost_confirmed td.c_catalog_unit_cost {
|
|
||||||
background-color: #cfc;
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
% if allow_edit_invoice_unit_cost:
|
|
||||||
td.c_invoice_unit_cost {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #fcc;
|
|
||||||
}
|
|
||||||
tr.invoice_cost_confirmed td.c_invoice_unit_cost {
|
|
||||||
background-color: #cfc;
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
</style>
|
|
||||||
% elif not use_buefy and not batch.executed and master.has_perm('edit_row'):
|
|
||||||
<style type="text/css">
|
|
||||||
.grid tr:not(.header) td.catalog_unit_cost,
|
|
||||||
.grid tr:not(.header) td.invoice_unit_cost {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #fcc;
|
|
||||||
}
|
}
|
||||||
.grid tr.catalog_cost_confirmed:not(.header) td.catalog_unit_cost,
|
tr.catalog_cost_confirmed td.c_catalog_unit_cost {
|
||||||
.grid tr.invoice_cost_confirmed:not(.header) td.invoice_unit_cost {
|
background-color: #cfc;
|
||||||
background-color: #cfc;
|
|
||||||
}
|
}
|
||||||
.grid td.catalog_unit_cost input,
|
% endif
|
||||||
.grid td.invoice_unit_cost input {
|
% if allow_edit_invoice_unit_cost:
|
||||||
width: 4rem;
|
td.c_invoice_unit_cost {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #fcc;
|
||||||
}
|
}
|
||||||
</style>
|
tr.invoice_cost_confirmed td.c_invoice_unit_cost {
|
||||||
% endif
|
background-color: #cfc;
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
</style>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_po_vs_invoice_helper()">
|
<%def name="render_po_vs_invoice_helper()">
|
||||||
% if use_buefy and master.handler.has_purchase_order(batch) and master.handler.has_invoice_file(batch):
|
% if master.handler.has_purchase_order(batch) and master.handler.has_invoice_file(batch):
|
||||||
<div class="object-helper">
|
<div class="object-helper">
|
||||||
<h3>PO vs. Invoice</h3>
|
<h3>PO vs. Invoice</h3>
|
||||||
<div class="object-helper-content">
|
<div class="object-helper-content">
|
||||||
|
@ -321,60 +42,51 @@
|
||||||
<div class="object-helper">
|
<div class="object-helper">
|
||||||
<h3>Tools</h3>
|
<h3>Tools</h3>
|
||||||
<div class="object-helper-content">
|
<div class="object-helper-content">
|
||||||
% if use_buefy:
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
@click="autoReceiveShowDialog = true"
|
||||||
@click="autoReceiveShowDialog = true"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="check">
|
||||||
icon-left="check">
|
Auto-Receive All Items
|
||||||
Auto-Receive All Items
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.form(url('{}.auto_receive'.format(route_prefix), uuid=batch.uuid), class_='autodisable')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.submit('submit', "Auto-Receive All Items")}
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
% if use_buefy:
|
<b-modal has-modal-card
|
||||||
<b-modal has-modal-card
|
:active.sync="autoReceiveShowDialog">
|
||||||
:active.sync="autoReceiveShowDialog">
|
<div class="modal-card">
|
||||||
<div class="modal-card">
|
|
||||||
|
|
||||||
<header class="modal-card-head">
|
<header class="modal-card-head">
|
||||||
<p class="modal-card-title">Auto-Receive All Items</p>
|
<p class="modal-card-title">Auto-Receive All Items</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
<p class="block">
|
<p class="block">
|
||||||
You can automatically set the "received" quantity to
|
You can automatically set the "received" quantity to
|
||||||
match the "shipped" quantity for all items, based on
|
match the "shipped" quantity for all items, based on
|
||||||
the invoice.
|
the invoice.
|
||||||
</p>
|
</p>
|
||||||
<p class="block">
|
<p class="block">
|
||||||
Would you like to do so?
|
Would you like to do so?
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer class="modal-card-foot">
|
<footer class="modal-card-foot">
|
||||||
<b-button @click="autoReceiveShowDialog = false">
|
<b-button @click="autoReceiveShowDialog = false">
|
||||||
Cancel
|
Cancel
|
||||||
</b-button>
|
</b-button>
|
||||||
${h.form(url('{}.auto_receive'.format(route_prefix), uuid=batch.uuid), **{'@submit': 'autoReceiveSubmitting = true'})}
|
${h.form(url('{}.auto_receive'.format(route_prefix), uuid=batch.uuid), **{'@submit': 'autoReceiveSubmitting = true'})}
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
native-type="submit"
|
native-type="submit"
|
||||||
:disabled="autoReceiveSubmitting"
|
:disabled="autoReceiveSubmitting"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="check">
|
icon-left="check">
|
||||||
{{ autoReceiveSubmitting ? "Working, please wait..." : "Auto-Receive All Items" }}
|
{{ autoReceiveSubmitting ? "Working, please wait..." : "Auto-Receive All Items" }}
|
||||||
</b-button>
|
</b-button>
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
@ -607,14 +319,3 @@
|
||||||
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
||||||
% if not use_buefy and master.handler.allow_truck_dump_receiving() and master.has_perm('edit_row'):
|
|
||||||
${h.form(url('{}.transform_unit_row'.format(route_prefix), uuid=batch.uuid), name='transform-unit-form')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('row_uuid')}
|
|
||||||
${h.end_form()}
|
|
||||||
|
|
||||||
<div id="transform-unit-dialog" style="display: none;">
|
|
||||||
<p>hello world</p>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
|
@ -4,479 +4,456 @@
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
% if use_buefy:
|
|
||||||
|
|
||||||
nav.panel {
|
nav.panel {
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-fields {
|
.header-fields {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-fields .field.is-horizontal {
|
.header-fields .field.is-horizontal {
|
||||||
margin-left: 3rem;
|
margin-left: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-fields .field.is-horizontal .field-label .label {
|
.header-fields .field.is-horizontal .field-label .label {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quantity-form-fields {
|
.quantity-form-fields {
|
||||||
margin: 2rem;
|
margin: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quantity-form-fields .field.is-horizontal .field-label .label {
|
.quantity-form-fields .field.is-horizontal .field-label .label {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
width: 8rem;
|
width: 8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.remove-credit .field.is-horizontal .field-label .label {
|
.remove-credit .field.is-horizontal .field-label .label {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
% endif
|
|
||||||
</style>
|
</style>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="object_helpers()">
|
<%def name="page_content()">
|
||||||
${parent.object_helpers()}
|
|
||||||
% if not use_buefy and master.row_editable(row) and not batch.is_truck_dump_child():
|
<b-field grouped class="header-fields">
|
||||||
<div class="object-helper">
|
|
||||||
<h3>Receiving Tools</h3>
|
<b-field label="Sequence" horizontal>
|
||||||
<div class="object-helper-content">
|
{{ rowData.sequence }}
|
||||||
<div style="white-space: nowrap;">
|
</b-field>
|
||||||
${h.link_to("Receive Product", url('{}.receive_row'.format(route_prefix), uuid=batch.uuid, row_uuid=row.uuid), class_='button autodisable')}
|
|
||||||
${h.link_to("Declare Credit", url('{}.declare_credit'.format(route_prefix), uuid=batch.uuid, row_uuid=row.uuid), class_='button autodisable')}
|
<b-field label="Status" horizontal>
|
||||||
|
{{ rowData.status }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field label="Calculated Total" horizontal>
|
||||||
|
{{ rowData.invoice_total_calculated }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<div style="display: flex;">
|
||||||
|
|
||||||
|
<nav class="panel">
|
||||||
|
<p class="panel-heading">Product</p>
|
||||||
|
<div class="panel-block">
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div>
|
||||||
|
${form.render_field_readonly('item_entry')}
|
||||||
|
% if row.product:
|
||||||
|
${form.render_field_readonly(product_key_field)}
|
||||||
|
${form.render_field_readonly('product')}
|
||||||
|
% else:
|
||||||
|
${form.render_field_readonly(product_key_field)}
|
||||||
|
% if product_key_field != 'upc':
|
||||||
|
${form.render_field_readonly('upc')}
|
||||||
|
% endif
|
||||||
|
${form.render_field_readonly('brand_name')}
|
||||||
|
${form.render_field_readonly('description')}
|
||||||
|
${form.render_field_readonly('size')}
|
||||||
|
% endif
|
||||||
|
${form.render_field_readonly('vendor_code')}
|
||||||
|
${form.render_field_readonly('case_quantity')}
|
||||||
|
${form.render_field_readonly('catalog_unit_cost')}
|
||||||
</div>
|
</div>
|
||||||
|
% if image_url:
|
||||||
|
<div class="is-pulled-right">
|
||||||
|
${h.image(image_url, "Product Image", width=150, height=150)}
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
</nav>
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="page_content()">
|
<nav class="panel">
|
||||||
% if use_buefy:
|
<p class="panel-heading">Quantities</p>
|
||||||
|
<div class="panel-block">
|
||||||
<b-field grouped class="header-fields">
|
<div>
|
||||||
|
<div class="quantity-form-fields">
|
||||||
<b-field label="Sequence" horizontal>
|
|
||||||
{{ rowData.sequence }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Status" horizontal>
|
|
||||||
{{ rowData.status }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Calculated Total" horizontal>
|
|
||||||
{{ rowData.invoice_total_calculated }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<div style="display: flex;">
|
|
||||||
|
|
||||||
<nav class="panel">
|
|
||||||
<p class="panel-heading">Product</p>
|
|
||||||
<div class="panel-block">
|
|
||||||
<div style="display: flex;">
|
|
||||||
<div>
|
|
||||||
${form.render_field_readonly('item_entry')}
|
|
||||||
% if row.product:
|
|
||||||
${form.render_field_readonly(product_key_field)}
|
|
||||||
${form.render_field_readonly('product')}
|
|
||||||
% else:
|
|
||||||
${form.render_field_readonly(product_key_field)}
|
|
||||||
% if product_key_field != 'upc':
|
|
||||||
${form.render_field_readonly('upc')}
|
|
||||||
% endif
|
|
||||||
${form.render_field_readonly('brand_name')}
|
|
||||||
${form.render_field_readonly('description')}
|
|
||||||
${form.render_field_readonly('size')}
|
|
||||||
% endif
|
|
||||||
${form.render_field_readonly('vendor_code')}
|
|
||||||
${form.render_field_readonly('case_quantity')}
|
|
||||||
${form.render_field_readonly('catalog_unit_cost')}
|
|
||||||
</div>
|
|
||||||
% if image_url:
|
|
||||||
<div class="is-pulled-right">
|
|
||||||
${h.image(image_url, "Product Image", width=150, height=150)}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<nav class="panel">
|
|
||||||
<p class="panel-heading">Quantities</p>
|
|
||||||
<div class="panel-block">
|
|
||||||
<div>
|
|
||||||
<div class="quantity-form-fields">
|
|
||||||
|
|
||||||
<b-field label="Ordered" horizontal>
|
|
||||||
{{ rowData.ordered }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<b-field label="Shipped" horizontal>
|
|
||||||
{{ rowData.shipped }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<b-field label="Received" horizontal
|
|
||||||
v-if="rowData.received">
|
|
||||||
{{ rowData.received }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Damaged" horizontal
|
|
||||||
v-if="rowData.damaged">
|
|
||||||
{{ rowData.damaged }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Expired" horizontal
|
|
||||||
v-if="rowData.expired">
|
|
||||||
{{ rowData.expired }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Mispick" horizontal
|
|
||||||
v-if="rowData.mispick">
|
|
||||||
{{ rowData.mispick }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Missing" horizontal
|
|
||||||
v-if="rowData.missing">
|
|
||||||
{{ rowData.missing }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% if master.has_perm('edit_row') and master.row_editable(row):
|
|
||||||
<div class="buttons">
|
|
||||||
<b-button type="is-primary"
|
|
||||||
@click="accountForProductInit()"
|
|
||||||
icon-pack="fas"
|
|
||||||
icon-left="check">
|
|
||||||
Account for Product
|
|
||||||
</b-button>
|
|
||||||
<b-button type="is-warning"
|
|
||||||
@click="declareCreditInit()"
|
|
||||||
:disabled="!rowData.received"
|
|
||||||
icon-pack="fas"
|
|
||||||
icon-left="thumbs-down">
|
|
||||||
Declare Credit
|
|
||||||
</b-button>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<b-modal has-modal-card
|
|
||||||
:active.sync="accountForProductShowDialog">
|
|
||||||
<div class="modal-card">
|
|
||||||
|
|
||||||
<header class="modal-card-head">
|
|
||||||
<p class="modal-card-title">Account for Product</p>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<section class="modal-card-body">
|
|
||||||
|
|
||||||
<p class="block">
|
|
||||||
This is for declaring that you have encountered some
|
|
||||||
amount of the product. Ideally you will just
|
|
||||||
"receive" it normally, but you can indicate a "credit"
|
|
||||||
state if there is something amiss.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<b-field grouped>
|
|
||||||
|
|
||||||
% if allow_cases:
|
|
||||||
<b-field label="Case Qty.">
|
|
||||||
<span class="control">
|
|
||||||
{{ rowData.case_quantity }}
|
|
||||||
</span>
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<span class="control">
|
|
||||||
|
|
||||||
</span>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
<b-field label="Product State"
|
|
||||||
:type="accountForProductMode ? null : 'is-danger'">
|
|
||||||
<b-select v-model="accountForProductMode">
|
|
||||||
<option v-for="mode in possibleReceivingModes"
|
|
||||||
:key="mode"
|
|
||||||
:value="mode">
|
|
||||||
{{ mode }}
|
|
||||||
</option>
|
|
||||||
</b-select>
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Expiration Date"
|
|
||||||
v-show="accountForProductMode == 'expired'"
|
|
||||||
:type="accountForProductExpiration ? null : 'is-danger'">
|
|
||||||
<tailbone-datepicker v-model="accountForProductExpiration">
|
|
||||||
</tailbone-datepicker>
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
|
<b-field label="Ordered" horizontal>
|
||||||
|
{{ rowData.ordered }}
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<div class="level">
|
<hr />
|
||||||
<div class="level-left">
|
|
||||||
|
|
||||||
<div class="level-item">
|
<b-field label="Shipped" horizontal>
|
||||||
<numeric-input v-model="accountForProductQuantity"
|
{{ rowData.shipped }}
|
||||||
ref="accountForProductQuantityInput">
|
</b-field>
|
||||||
</numeric-input>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="level-item">
|
<hr />
|
||||||
% if allow_cases:
|
|
||||||
<b-field>
|
|
||||||
<b-radio-button v-model="accountForProductUOM"
|
|
||||||
@click.native="accountForProductUOMClicked('units')"
|
|
||||||
native-value="units">
|
|
||||||
Units
|
|
||||||
</b-radio-button>
|
|
||||||
<b-radio-button v-model="accountForProductUOM"
|
|
||||||
@click.native="accountForProductUOMClicked('cases')"
|
|
||||||
native-value="cases">
|
|
||||||
Cases
|
|
||||||
</b-radio-button>
|
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<b-field>
|
|
||||||
<input type="hidden" v-model="accountForProductUOM" />
|
|
||||||
Units
|
|
||||||
</b-field>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% if allow_cases:
|
<b-field label="Received" horizontal
|
||||||
<div class="level-item"
|
v-if="rowData.received">
|
||||||
v-if="accountForProductUOM == 'cases' && accountForProductQuantity">
|
{{ rowData.received }}
|
||||||
= {{ accountForProductTotalUnits }}
|
</b-field>
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
|
<b-field label="Damaged" horizontal
|
||||||
|
v-if="rowData.damaged">
|
||||||
|
{{ rowData.damaged }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field label="Expired" horizontal
|
||||||
|
v-if="rowData.expired">
|
||||||
|
{{ rowData.expired }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field label="Mispick" horizontal
|
||||||
|
v-if="rowData.mispick">
|
||||||
|
{{ rowData.mispick }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field label="Missing" horizontal
|
||||||
|
v-if="rowData.missing">
|
||||||
|
{{ rowData.missing }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
% if master.has_perm('edit_row') and master.row_editable(row):
|
||||||
|
<div class="buttons">
|
||||||
|
<b-button type="is-primary"
|
||||||
|
@click="accountForProductInit()"
|
||||||
|
icon-pack="fas"
|
||||||
|
icon-left="check">
|
||||||
|
Account for Product
|
||||||
|
</b-button>
|
||||||
|
<b-button type="is-warning"
|
||||||
|
@click="declareCreditInit()"
|
||||||
|
:disabled="!rowData.received"
|
||||||
|
icon-pack="fas"
|
||||||
|
icon-left="thumbs-down">
|
||||||
|
Declare Credit
|
||||||
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
% endif
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<footer class="modal-card-foot">
|
|
||||||
<b-button @click="accountForProductShowDialog = false">
|
|
||||||
Cancel
|
|
||||||
</b-button>
|
|
||||||
<b-button type="is-primary"
|
|
||||||
@click="accountForProductSubmit()"
|
|
||||||
:disabled="accountForProductSubmitDisabled"
|
|
||||||
icon-pack="fas"
|
|
||||||
icon-left="check">
|
|
||||||
{{ accountForProductSubmitting ? "Working, please wait..." : "Account for Product" }}
|
|
||||||
</b-button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<b-modal has-modal-card
|
</div>
|
||||||
:active.sync="declareCreditShowDialog">
|
|
||||||
<div class="modal-card">
|
|
||||||
|
|
||||||
<header class="modal-card-head">
|
<b-modal has-modal-card
|
||||||
<p class="modal-card-title">Declare Credit</p>
|
:active.sync="accountForProductShowDialog">
|
||||||
</header>
|
<div class="modal-card">
|
||||||
|
|
||||||
<section class="modal-card-body">
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title">Account for Product</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
<p class="block">
|
<section class="modal-card-body">
|
||||||
This is for <span class="is-italic">converting</span>
|
|
||||||
some amount you <span class="is-italic">already
|
|
||||||
received</span>, and now declaring there is something
|
|
||||||
wrong with it.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<b-field grouped>
|
<p class="block">
|
||||||
|
This is for declaring that you have encountered some
|
||||||
|
amount of the product. Ideally you will just
|
||||||
|
"receive" it normally, but you can indicate a "credit"
|
||||||
|
state if there is something amiss.
|
||||||
|
</p>
|
||||||
|
|
||||||
<b-field label="Received">
|
<b-field grouped>
|
||||||
|
|
||||||
|
% if allow_cases:
|
||||||
|
<b-field label="Case Qty.">
|
||||||
<span class="control">
|
<span class="control">
|
||||||
{{ rowData.received }}
|
{{ rowData.case_quantity }}
|
||||||
</span>
|
</span>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<span class="control">
|
<span class="control">
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
|
% endif
|
||||||
|
|
||||||
<b-field label="Credit Type"
|
<b-field label="Product State"
|
||||||
:type="declareCreditType ? null : 'is-danger'">
|
:type="accountForProductMode ? null : 'is-danger'">
|
||||||
<b-select v-model="declareCreditType">
|
<b-select v-model="accountForProductMode">
|
||||||
<option v-for="typ in possibleCreditTypes"
|
<option v-for="mode in possibleReceivingModes"
|
||||||
:key="typ"
|
:key="mode"
|
||||||
:value="typ">
|
:value="mode">
|
||||||
{{ typ }}
|
{{ mode }}
|
||||||
</option>
|
</option>
|
||||||
</b-select>
|
</b-select>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field label="Expiration Date"
|
<b-field label="Expiration Date"
|
||||||
v-show="declareCreditType == 'expired'"
|
v-show="accountForProductMode == 'expired'"
|
||||||
:type="declareCreditExpiration ? null : 'is-danger'">
|
:type="accountForProductExpiration ? null : 'is-danger'">
|
||||||
<tailbone-datepicker v-model="declareCreditExpiration">
|
<tailbone-datepicker v-model="accountForProductExpiration">
|
||||||
</tailbone-datepicker>
|
</tailbone-datepicker>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<div class="level">
|
<div class="level">
|
||||||
<div class="level-left">
|
<div class="level-left">
|
||||||
|
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<numeric-input v-model="declareCreditQuantity"
|
<numeric-input v-model="accountForProductQuantity"
|
||||||
ref="declareCreditQuantityInput">
|
ref="accountForProductQuantityInput">
|
||||||
</numeric-input>
|
</numeric-input>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="level-item">
|
|
||||||
% if allow_cases:
|
|
||||||
<b-field>
|
|
||||||
<b-radio-button v-model="declareCreditUOM"
|
|
||||||
@click.native="declareCreditUOMClicked('units')"
|
|
||||||
native-value="units">
|
|
||||||
Units
|
|
||||||
</b-radio-button>
|
|
||||||
<b-radio-button v-model="declareCreditUOM"
|
|
||||||
@click.native="declareCreditUOMClicked('cases')"
|
|
||||||
native-value="cases">
|
|
||||||
Cases
|
|
||||||
</b-radio-button>
|
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<b-field>
|
|
||||||
<input type="hidden" v-model="declareCreditUOM" />
|
|
||||||
Units
|
|
||||||
</b-field>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% if allow_cases:
|
|
||||||
<div class="level-item"
|
|
||||||
v-if="declareCreditUOM == 'cases' && declareCreditQuantity">
|
|
||||||
= {{ declareCreditTotalUnits }}
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
<div class="level-item">
|
||||||
|
% if allow_cases:
|
||||||
|
<b-field>
|
||||||
|
<b-radio-button v-model="accountForProductUOM"
|
||||||
|
@click.native="accountForProductUOMClicked('units')"
|
||||||
|
native-value="units">
|
||||||
|
Units
|
||||||
|
</b-radio-button>
|
||||||
|
<b-radio-button v-model="accountForProductUOM"
|
||||||
|
@click.native="accountForProductUOMClicked('cases')"
|
||||||
|
native-value="cases">
|
||||||
|
Cases
|
||||||
|
</b-radio-button>
|
||||||
|
</b-field>
|
||||||
|
% else:
|
||||||
|
<b-field>
|
||||||
|
<input type="hidden" v-model="accountForProductUOM" />
|
||||||
|
Units
|
||||||
|
</b-field>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
|
||||||
<footer class="modal-card-foot">
|
% if allow_cases:
|
||||||
<b-button @click="declareCreditShowDialog = false">
|
<div class="level-item"
|
||||||
Cancel
|
v-if="accountForProductUOM == 'cases' && accountForProductQuantity">
|
||||||
</b-button>
|
= {{ accountForProductTotalUnits }}
|
||||||
<b-button type="is-warning"
|
</div>
|
||||||
@click="declareCreditSubmit()"
|
% endif
|
||||||
:disabled="declareCreditSubmitDisabled"
|
|
||||||
icon-pack="fas"
|
|
||||||
icon-left="thumbs-down">
|
|
||||||
{{ declareCreditSubmitting ? "Working, please wait..." : "Declare this Credit" }}
|
|
||||||
</b-button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</b-modal>
|
|
||||||
|
|
||||||
<nav class="panel" >
|
|
||||||
<p class="panel-heading">Credits</p>
|
|
||||||
<div class="panel-block">
|
|
||||||
<div>
|
|
||||||
${form.render_field_value('credits')}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
|
||||||
|
|
||||||
<b-modal has-modal-card
|
</section>
|
||||||
:active.sync="removeCreditShowDialog">
|
|
||||||
<div class="modal-card remove-credit">
|
|
||||||
|
|
||||||
<header class="modal-card-head">
|
<footer class="modal-card-foot">
|
||||||
<p class="modal-card-title">Un-Declare Credit</p>
|
<b-button @click="accountForProductShowDialog = false">
|
||||||
</header>
|
Cancel
|
||||||
|
</b-button>
|
||||||
|
<b-button type="is-primary"
|
||||||
|
@click="accountForProductSubmit()"
|
||||||
|
:disabled="accountForProductSubmitDisabled"
|
||||||
|
icon-pack="fas"
|
||||||
|
icon-left="check">
|
||||||
|
{{ accountForProductSubmitting ? "Working, please wait..." : "Account for Product" }}
|
||||||
|
</b-button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</b-modal>
|
||||||
|
|
||||||
<section class="modal-card-body">
|
<b-modal has-modal-card
|
||||||
|
:active.sync="declareCreditShowDialog">
|
||||||
|
<div class="modal-card">
|
||||||
|
|
||||||
<p class="block">
|
<header class="modal-card-head">
|
||||||
If you un-declare this credit, the quantity below will
|
<p class="modal-card-title">Declare Credit</p>
|
||||||
be added back to the
|
</header>
|
||||||
<span class="has-text-weight-bold">Received</span> tally.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<b-field label="Credit Type" horizontal>
|
<section class="modal-card-body">
|
||||||
{{ removeCreditRow.credit_type }}
|
|
||||||
</b-field>
|
|
||||||
|
|
||||||
<b-field label="Quantity" horizontal>
|
<p class="block">
|
||||||
{{ removeCreditRow.shorted }}
|
This is for <span class="is-italic">converting</span>
|
||||||
</b-field>
|
some amount you <span class="is-italic">already
|
||||||
|
received</span>, and now declaring there is something
|
||||||
|
wrong with it.
|
||||||
|
</p>
|
||||||
|
|
||||||
</section>
|
<b-field grouped>
|
||||||
|
|
||||||
<footer class="modal-card-foot">
|
<b-field label="Received">
|
||||||
<b-button @click="removeCreditShowDialog = false">
|
<span class="control">
|
||||||
Cancel
|
{{ rowData.received }}
|
||||||
</b-button>
|
</span>
|
||||||
<b-button type="is-danger"
|
</b-field>
|
||||||
@click="removeCreditSubmit()"
|
|
||||||
:disabled="removeCreditSubmitting"
|
<span class="control">
|
||||||
icon-pack="fas"
|
|
||||||
icon-left="trash">
|
</span>
|
||||||
{{ removeCreditSubmitting ? "Working, please wait..." : "Un-Declare this Credit" }}
|
|
||||||
</b-button>
|
<b-field label="Credit Type"
|
||||||
</footer>
|
:type="declareCreditType ? null : 'is-danger'">
|
||||||
|
<b-select v-model="declareCreditType">
|
||||||
|
<option v-for="typ in possibleCreditTypes"
|
||||||
|
:key="typ"
|
||||||
|
:value="typ">
|
||||||
|
{{ typ }}
|
||||||
|
</option>
|
||||||
|
</b-select>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field label="Expiration Date"
|
||||||
|
v-show="declareCreditType == 'expired'"
|
||||||
|
:type="declareCreditExpiration ? null : 'is-danger'">
|
||||||
|
<tailbone-datepicker v-model="declareCreditExpiration">
|
||||||
|
</tailbone-datepicker>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<div class="level">
|
||||||
|
<div class="level-left">
|
||||||
|
|
||||||
|
<div class="level-item">
|
||||||
|
<numeric-input v-model="declareCreditQuantity"
|
||||||
|
ref="declareCreditQuantityInput">
|
||||||
|
</numeric-input>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="level-item">
|
||||||
|
% if allow_cases:
|
||||||
|
<b-field>
|
||||||
|
<b-radio-button v-model="declareCreditUOM"
|
||||||
|
@click.native="declareCreditUOMClicked('units')"
|
||||||
|
native-value="units">
|
||||||
|
Units
|
||||||
|
</b-radio-button>
|
||||||
|
<b-radio-button v-model="declareCreditUOM"
|
||||||
|
@click.native="declareCreditUOMClicked('cases')"
|
||||||
|
native-value="cases">
|
||||||
|
Cases
|
||||||
|
</b-radio-button>
|
||||||
|
</b-field>
|
||||||
|
% else:
|
||||||
|
<b-field>
|
||||||
|
<input type="hidden" v-model="declareCreditUOM" />
|
||||||
|
Units
|
||||||
|
</b-field>
|
||||||
|
% endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
% if allow_cases:
|
||||||
|
<div class="level-item"
|
||||||
|
v-if="declareCreditUOM == 'cases' && declareCreditQuantity">
|
||||||
|
= {{ declareCreditTotalUnits }}
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</b-modal>
|
|
||||||
|
|
||||||
<div style="display: flex;">
|
</section>
|
||||||
|
|
||||||
% if master.batch_handler.has_purchase_order(batch):
|
<footer class="modal-card-foot">
|
||||||
<nav class="panel" >
|
<b-button @click="declareCreditShowDialog = false">
|
||||||
<p class="panel-heading">Purchase Order</p>
|
Cancel
|
||||||
<div class="panel-block">
|
</b-button>
|
||||||
<div>
|
<b-button type="is-warning"
|
||||||
${form.render_field_readonly('po_line_number')}
|
@click="declareCreditSubmit()"
|
||||||
${form.render_field_readonly('po_unit_cost')}
|
:disabled="declareCreditSubmitDisabled"
|
||||||
${form.render_field_readonly('po_case_size')}
|
icon-pack="fas"
|
||||||
${form.render_field_readonly('po_total')}
|
icon-left="thumbs-down">
|
||||||
</div>
|
{{ declareCreditSubmitting ? "Working, please wait..." : "Declare this Credit" }}
|
||||||
</div>
|
</b-button>
|
||||||
</nav>
|
</footer>
|
||||||
% endif
|
</div>
|
||||||
|
</b-modal>
|
||||||
% if master.batch_handler.has_invoice_file(batch):
|
|
||||||
<nav class="panel" >
|
|
||||||
<p class="panel-heading">Invoice</p>
|
|
||||||
<div class="panel-block">
|
|
||||||
<div>
|
|
||||||
${form.render_field_readonly('invoice_line_number')}
|
|
||||||
${form.render_field_readonly('invoice_unit_cost')}
|
|
||||||
${form.render_field_readonly('invoice_case_size')}
|
|
||||||
${form.render_field_readonly('invoice_total', label="Invoice Total")}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
|
<nav class="panel" >
|
||||||
|
<p class="panel-heading">Credits</p>
|
||||||
|
<div class="panel-block">
|
||||||
|
<div>
|
||||||
|
${form.render_field_value('credits')}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
% else:
|
<b-modal has-modal-card
|
||||||
## legacy / not buefy
|
:active.sync="removeCreditShowDialog">
|
||||||
${parent.page_content()}
|
<div class="modal-card remove-credit">
|
||||||
% endif
|
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<p class="modal-card-title">Un-Declare Credit</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="modal-card-body">
|
||||||
|
|
||||||
|
<p class="block">
|
||||||
|
If you un-declare this credit, the quantity below will
|
||||||
|
be added back to the
|
||||||
|
<span class="has-text-weight-bold">Received</span> tally.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<b-field label="Credit Type" horizontal>
|
||||||
|
{{ removeCreditRow.credit_type }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
<b-field label="Quantity" horizontal>
|
||||||
|
{{ removeCreditRow.shorted }}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer class="modal-card-foot">
|
||||||
|
<b-button @click="removeCreditShowDialog = false">
|
||||||
|
Cancel
|
||||||
|
</b-button>
|
||||||
|
<b-button type="is-danger"
|
||||||
|
@click="removeCreditSubmit()"
|
||||||
|
:disabled="removeCreditSubmitting"
|
||||||
|
icon-pack="fas"
|
||||||
|
icon-left="trash">
|
||||||
|
{{ removeCreditSubmitting ? "Working, please wait..." : "Un-Declare this Credit" }}
|
||||||
|
</b-button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</b-modal>
|
||||||
|
|
||||||
|
<div style="display: flex;">
|
||||||
|
|
||||||
|
% if master.batch_handler.has_purchase_order(batch):
|
||||||
|
<nav class="panel" >
|
||||||
|
<p class="panel-heading">Purchase Order</p>
|
||||||
|
<div class="panel-block">
|
||||||
|
<div>
|
||||||
|
${form.render_field_readonly('po_line_number')}
|
||||||
|
${form.render_field_readonly('po_unit_cost')}
|
||||||
|
${form.render_field_readonly('po_case_size')}
|
||||||
|
${form.render_field_readonly('po_total')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
% endif
|
||||||
|
|
||||||
|
% if master.batch_handler.has_invoice_file(batch):
|
||||||
|
<nav class="panel" >
|
||||||
|
<p class="panel-heading">Invoice</p>
|
||||||
|
<div class="panel-block">
|
||||||
|
<div>
|
||||||
|
${form.render_field_readonly('invoice_line_number')}
|
||||||
|
${form.render_field_readonly('invoice_unit_cost')}
|
||||||
|
${form.render_field_readonly('invoice_case_size')}
|
||||||
|
${form.render_field_readonly('invoice_total', label="Invoice Total")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
% endif
|
||||||
|
|
||||||
|
</div>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
|
|
|
@ -1,47 +1,14 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/create.mako" />
|
<%inherit file="/master/create.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var report_descriptions = ${json.dumps(report_descriptions)|n};
|
|
||||||
|
|
||||||
function show_description(key) {
|
|
||||||
var desc = report_descriptions[key];
|
|
||||||
$('#report-description').text(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
var report_type = $('select[name="report_type"]');
|
|
||||||
|
|
||||||
report_type.change(function(event) {
|
|
||||||
show_description(report_type.val());
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
|
|
||||||
% if use_form:
|
% if use_form:
|
||||||
% if use_buefy:
|
#report-description {
|
||||||
#report-description {
|
margin-left: 2em;
|
||||||
margin-left: 2em;
|
}
|
||||||
}
|
|
||||||
% else:
|
|
||||||
#report-description {
|
|
||||||
margin-top: 2em;
|
|
||||||
margin-left: 2em;
|
|
||||||
}
|
|
||||||
% endif
|
|
||||||
% else:
|
% else:
|
||||||
.report-selection {
|
.report-selection {
|
||||||
margin-left: 10em;
|
margin-left: 10em;
|
||||||
|
@ -69,19 +36,7 @@
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
% if use_form:
|
% if use_form:
|
||||||
% if use_buefy:
|
${parent.page_content()}
|
||||||
${parent.page_content()}
|
|
||||||
% else:
|
|
||||||
<div class="form-wrapper">
|
|
||||||
<p>Please select the type of report you wish to generate.</p>
|
|
||||||
|
|
||||||
<div style="display: flex;">
|
|
||||||
${form.render()|n}
|
|
||||||
<div id="report-description"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div><!-- form-wrapper -->
|
|
||||||
% endif
|
|
||||||
% else:
|
% else:
|
||||||
<div>
|
<div>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -24,11 +24,5 @@
|
||||||
</div>
|
</div>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form()">
|
|
||||||
% if not use_buefy:
|
|
||||||
<p style="padding: 1em;">${report.__doc__}</p>
|
|
||||||
% endif
|
|
||||||
${parent.render_form()}
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -4,83 +4,47 @@
|
||||||
<%def name="title()">Report : Inventory Worksheet</%def>
|
<%def name="title()">Report : Inventory Worksheet</%def>
|
||||||
|
|
||||||
<%def name="page_content()">
|
<%def name="page_content()">
|
||||||
% if use_buefy:
|
|
||||||
|
|
||||||
<p class="block">
|
<p class="block">
|
||||||
Please provide the following criteria to generate your report:
|
Please provide the following criteria to generate your report:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
${h.form(request.current_route_url())}
|
${h.form(request.current_route_url())}
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
|
|
||||||
<b-field label="Department">
|
<b-field label="Department">
|
||||||
<b-select name="department">
|
<b-select name="department">
|
||||||
<option v-for="dept in departments"
|
<option v-for="dept in departments"
|
||||||
:key="dept.uuid"
|
:key="dept.uuid"
|
||||||
:value="dept.uuid">
|
:value="dept.uuid">
|
||||||
{{ dept.name }}
|
{{ dept.name }}
|
||||||
</option>
|
</option>
|
||||||
</b-select>
|
</b-select>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field>
|
<b-field>
|
||||||
<b-checkbox name="weighted-only" native-value="1">
|
<b-checkbox name="weighted-only" native-value="1">
|
||||||
Only include items which are sold by weight.
|
Only include items which are sold by weight.
|
||||||
</b-checkbox>
|
</b-checkbox>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<b-field>
|
<b-field>
|
||||||
<b-checkbox name="exclude-not-for-sale" :value="true"
|
<b-checkbox name="exclude-not-for-sale" :value="true"
|
||||||
native-value="1">
|
native-value="1">
|
||||||
Exclude items marked "not for sale".
|
Exclude items marked "not for sale".
|
||||||
</b-checkbox>
|
</b-checkbox>
|
||||||
</b-field>
|
</b-field>
|
||||||
|
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
native-type="submit"
|
native-type="submit"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="arrow-circle-right">
|
icon-left="arrow-circle-right">
|
||||||
Generate Report
|
Generate Report
|
||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
|
|
||||||
% else:
|
|
||||||
|
|
||||||
<p>Please provide the following criteria to generate your report:</p>
|
|
||||||
<br />
|
|
||||||
|
|
||||||
${h.form(request.current_route_url())}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label for="department">Department</label>
|
|
||||||
<div class="field">
|
|
||||||
<select name="department">
|
|
||||||
% for department in departments:
|
|
||||||
<option value="${department.uuid}">${department.name}</option>
|
|
||||||
% endfor
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
${h.checkbox('weighted-only', label="Only include items which are sold by weight.")}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field-wrapper">
|
|
||||||
${h.checkbox('exclude-not-for-sale', label="Exclude items marked \"not for sale\".", checked=True)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
${h.submit('submit', "Generate Report")}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${h.end_form()}
|
|
||||||
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
|
|
|
@ -6,24 +6,6 @@
|
||||||
${h.stylesheet_link(request.static_url('tailbone:static/css/perms.css'))}
|
${h.stylesheet_link(request.static_url('tailbone:static/css/perms.css'))}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="page_content()">
|
|
||||||
${parent.page_content()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<h2>Users</h2>
|
|
||||||
|
|
||||||
% if instance is guest_role:
|
|
||||||
<p>The guest role is implied for all anonymous users, i.e. when not logged in.</p>
|
|
||||||
% elif instance is authenticated_role:
|
|
||||||
<p>The authenticated role is implied for all users, but only when logged in.</p>
|
|
||||||
% elif users:
|
|
||||||
<p>The following users are assigned to this role:</p>
|
|
||||||
${users.render_grid()|n}
|
|
||||||
% else:
|
|
||||||
<p>There are no users assigned to this role.</p>
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
${parent.modify_this_page_vars()}
|
${parent.modify_this_page_vars()}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
|
@ -1,41 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
% if not email.get_template('html'):
|
|
||||||
$(function() {
|
|
||||||
$('#preview-html').button('disable');
|
|
||||||
$('#preview-html').attr('title', "There is no HTML template on file for this email.");
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
% if not email.get_template('txt'):
|
|
||||||
$(function() {
|
|
||||||
$('#preview-txt').button('disable');
|
|
||||||
$('#preview-txt').attr('title', "There is no TXT template on file for this email.");
|
|
||||||
});
|
|
||||||
% endif
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="render_form()">
|
|
||||||
${parent.render_form()}
|
|
||||||
% if not use_buefy:
|
|
||||||
${h.form(url('email.preview'), name='send-email-preview', class_='autodisable')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.hidden('email_key', value=instance['key'])}
|
|
||||||
${h.link_to("Preview HTML", '{}?key={}&type=html'.format(url('email.preview'), instance['key']), id='preview-html', class_='button', target='_blank')}
|
|
||||||
${h.link_to("Preview TXT", '{}?key={}&type=txt'.format(url('email.preview'), instance['key']), id='preview-txt', class_='button', target='_blank')}
|
|
||||||
or
|
|
||||||
${h.text('recipient', value=request.user.email_address or '')}
|
|
||||||
${h.submit('send_{}'.format(instance['key']), value="Send Preview Email")}
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="render_buefy_form()">
|
<%def name="render_buefy_form()">
|
||||||
${parent.render_buefy_form()}
|
${parent.render_buefy_form()}
|
||||||
<email-preview-tools></email-preview-tools>
|
<email-preview-tools></email-preview-tools>
|
||||||
|
|
|
@ -1,20 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
$('#restart-client').click(function() {
|
|
||||||
disable_button(this);
|
|
||||||
location.href = '${url('tempmon.clients.restart', uuid=instance.uuid)}';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
${parent.context_menu_items()}
|
${parent.context_menu_items()}
|
||||||
% if request.has_perm('tempmon.appliances.dashboard'):
|
% if request.has_perm('tempmon.appliances.dashboard'):
|
||||||
|
@ -27,14 +13,10 @@
|
||||||
<div class="object-helper">
|
<div class="object-helper">
|
||||||
<h3>Client Tools</h3>
|
<h3>Client Tools</h3>
|
||||||
<div class="object-helper-content">
|
<div class="object-helper-content">
|
||||||
% if use_buefy:
|
<once-button tag="a" href="${url('{}.restart'.format(route_prefix), uuid=instance.uuid)}"
|
||||||
<once-button tag="a" href="${url('{}.restart'.format(route_prefix), uuid=instance.uuid)}"
|
type="is-primary"
|
||||||
type="is-primary"
|
text="Restart tempmon-client daemon">
|
||||||
text="Restart tempmon-client daemon">
|
</once-button>
|
||||||
</once-button>
|
|
||||||
% else:
|
|
||||||
<button type="button" id="restart-client">Restart tempmon-client daemon</button>
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -8,178 +8,54 @@
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js"></script>
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var contexts = {};
|
|
||||||
var charts = {};
|
|
||||||
|
|
||||||
function fetchReadings(appliance_uuid) {
|
|
||||||
if (appliance_uuid === undefined) {
|
|
||||||
appliance_uuid = $('#appliance_uuid').val();
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.form-wrapper').mask("Fetching data");
|
|
||||||
|
|
||||||
if (Object.keys(charts).length) {
|
|
||||||
Object.keys(charts).forEach(function(key) {
|
|
||||||
charts[key].destroy();
|
|
||||||
delete charts[key];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = '${url("tempmon.dashboard.readings")}';
|
|
||||||
var params = {'appliance_uuid': appliance_uuid};
|
|
||||||
$.get(url, params, function(data) {
|
|
||||||
|
|
||||||
if (data.probes) {
|
|
||||||
data.probes.forEach(function(probe) {
|
|
||||||
charts[probe.uuid] = new Chart(contexts[probe.uuid], {
|
|
||||||
type: 'scatter',
|
|
||||||
data: {
|
|
||||||
datasets: [{
|
|
||||||
label: probe.description,
|
|
||||||
data: probe.readings
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
xAxes: [{
|
|
||||||
type: 'time',
|
|
||||||
time: {unit: 'minute'},
|
|
||||||
position: 'bottom'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// TODO: should improve this
|
|
||||||
alert(data.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.form-wrapper').unmask();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
% for probe in appliance.probes:
|
|
||||||
contexts['${probe.uuid}'] = $('#tempchart-${probe.uuid}');
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
$('#appliance_uuid').selectmenu({
|
|
||||||
change: function(event, ui) {
|
|
||||||
$('.form-wrapper').mask("Fetching data");
|
|
||||||
$(this).parents('form').submit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fetchReadings();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_this_page()">
|
<%def name="render_this_page()">
|
||||||
% if use_buefy:
|
${h.form(request.current_route_url(), ref='applianceForm')}
|
||||||
|
${h.csrf_token(request)}
|
||||||
|
<div class="level-left">
|
||||||
|
|
||||||
${h.form(request.current_route_url(), ref='applianceForm')}
|
<div class="level-item">
|
||||||
${h.csrf_token(request)}
|
<b-field label="Appliance" horizontal>
|
||||||
<div class="level-left">
|
<b-select name="appliance_uuid"
|
||||||
|
v-model="applianceUUID"
|
||||||
<div class="level-item">
|
@input="$refs.applianceForm.submit()">
|
||||||
<b-field label="Appliance" horizontal>
|
<option v-for="appliance in appliances"
|
||||||
<b-select name="appliance_uuid"
|
:key="appliance.uuid"
|
||||||
v-model="applianceUUID"
|
:value="appliance.uuid">
|
||||||
@input="$refs.applianceForm.submit()">
|
{{ appliance.name }}
|
||||||
<option v-for="appliance in appliances"
|
</option>
|
||||||
:key="appliance.uuid"
|
</b-select>
|
||||||
:value="appliance.uuid">
|
</b-field>
|
||||||
{{ appliance.name }}
|
|
||||||
</option>
|
|
||||||
</b-select>
|
|
||||||
</b-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% if appliance:
|
|
||||||
<div class="level-item">
|
|
||||||
<a href="${url('tempmon.appliances.view', uuid=appliance.uuid)}">
|
|
||||||
${h.image(url('tempmon.appliances.thumbnail', uuid=appliance.uuid), "")}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
</div>
|
|
||||||
${h.end_form()}
|
|
||||||
|
|
||||||
% if appliance and appliance.probes:
|
|
||||||
% for probe in appliance.probes:
|
|
||||||
<h4 class="is-size-4">
|
|
||||||
Probe: ${h.link_to(probe.description, url('tempmon.probes.graph', uuid=probe.uuid))}
|
|
||||||
(status: ${enum.TEMPMON_PROBE_STATUS[probe.status]})
|
|
||||||
</h4>
|
|
||||||
% if probe.enabled:
|
|
||||||
<canvas ref="tempchart-${probe.uuid}" width="400" height="60"></canvas>
|
|
||||||
% else:
|
|
||||||
<p>This probe is not enabled.</p>
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
% elif appliance:
|
|
||||||
<h3>This appliance has no probes configured!</h3>
|
|
||||||
% else:
|
|
||||||
<h3>Please choose an appliance.</h3>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% else:
|
|
||||||
## not buefy
|
|
||||||
<div style="display: flex;">
|
|
||||||
|
|
||||||
<div class="form-wrapper">
|
|
||||||
<div class="form">
|
|
||||||
${h.form(request.current_route_url())}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
% if use_buefy:
|
|
||||||
<b-field horizontal label="Appliance">
|
|
||||||
${appliance_select}
|
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Appliance</label>
|
|
||||||
<div class="field">
|
|
||||||
${appliance_select}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
${h.end_form()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="${url('tempmon.appliances.view', uuid=appliance.uuid)}">
|
% if appliance:
|
||||||
${h.image(url('tempmon.appliances.thumbnail', uuid=appliance.uuid), "")}
|
<div class="level-item">
|
||||||
</a>
|
<a href="${url('tempmon.appliances.view', uuid=appliance.uuid)}">
|
||||||
</div>
|
${h.image(url('tempmon.appliances.thumbnail', uuid=appliance.uuid), "")}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
|
||||||
% if appliance.probes:
|
</div>
|
||||||
|
${h.end_form()}
|
||||||
|
|
||||||
|
% if appliance and appliance.probes:
|
||||||
% for probe in appliance.probes:
|
% for probe in appliance.probes:
|
||||||
<h3>
|
<h4 class="is-size-4">
|
||||||
Probe: ${h.link_to(probe.description, url('tempmon.probes.graph', uuid=probe.uuid))}
|
Probe: ${h.link_to(probe.description, url('tempmon.probes.graph', uuid=probe.uuid))}
|
||||||
(status: ${enum.TEMPMON_PROBE_STATUS[probe.status]})
|
(status: ${enum.TEMPMON_PROBE_STATUS[probe.status]})
|
||||||
</h3>
|
</h4>
|
||||||
% if probe.enabled:
|
% if probe.enabled:
|
||||||
% if use_buefy:
|
<canvas ref="tempchart-${probe.uuid}" width="400" height="60"></canvas>
|
||||||
<canvas ref="tempchart" width="400" height="150"></canvas>
|
|
||||||
% else:
|
|
||||||
<canvas id="tempchart-${probe.uuid}" width="400" height="60"></canvas>
|
|
||||||
% endif
|
|
||||||
% else:
|
% else:
|
||||||
<p>This probe is not enabled.</p>
|
<p>This probe is not enabled.</p>
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
% else:
|
% elif appliance:
|
||||||
<h3>This appliance has no probes configured!</h3>
|
<h3>This appliance has no probes configured!</h3>
|
||||||
% endif
|
% else:
|
||||||
|
<h3>Please choose an appliance.</h3>
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
|
@ -6,71 +6,6 @@
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js"></script>
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
var ctx = null;
|
|
||||||
var chart = null;
|
|
||||||
|
|
||||||
function fetchReadings(timeRange) {
|
|
||||||
if (timeRange === undefined) {
|
|
||||||
timeRange = $('#time-range').val();
|
|
||||||
}
|
|
||||||
|
|
||||||
var timeUnit;
|
|
||||||
if (timeRange == 'last hour') {
|
|
||||||
timeUnit = 'minute';
|
|
||||||
} else if (['last 6 hours', 'last day'].includes(timeRange)) {
|
|
||||||
timeUnit = 'hour';
|
|
||||||
} else {
|
|
||||||
timeUnit = 'day';
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.form-wrapper').mask("Fetching data");
|
|
||||||
if (chart) {
|
|
||||||
chart.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
$.get('${url('{}.graph_readings'.format(route_prefix), uuid=probe.uuid)}', {'time-range': timeRange}, function(data) {
|
|
||||||
|
|
||||||
chart = new Chart(ctx, {
|
|
||||||
type: 'scatter',
|
|
||||||
data: {
|
|
||||||
datasets: [{
|
|
||||||
label: "${probe.description}",
|
|
||||||
data: data
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
scales: {
|
|
||||||
xAxes: [{
|
|
||||||
type: 'time',
|
|
||||||
time: {unit: timeUnit},
|
|
||||||
position: 'bottom'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.form-wrapper').unmask();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
ctx = $('#tempchart');
|
|
||||||
|
|
||||||
$('#time-range').selectmenu({
|
|
||||||
change: function(event, ui) {
|
|
||||||
fetchReadings(ui.item.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fetchReadings();
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
|
@ -89,50 +24,23 @@
|
||||||
<div class="form-wrapper">
|
<div class="form-wrapper">
|
||||||
<div class="form">
|
<div class="form">
|
||||||
|
|
||||||
% if use_buefy:
|
<b-field horizontal label="Appliance">
|
||||||
<b-field horizontal label="Appliance">
|
<div>
|
||||||
<div>
|
% if probe.appliance:
|
||||||
% if probe.appliance:
|
<a href="${url('tempmon.appliances.view', uuid=probe.appliance.uuid)}">${probe.appliance}</a>
|
||||||
<a href="${url('tempmon.appliances.view', uuid=probe.appliance.uuid)}">${probe.appliance}</a>
|
% endif
|
||||||
% endif
|
</div>
|
||||||
</div>
|
</b-field>
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Appliance</label>
|
|
||||||
<div class="field">
|
|
||||||
% if probe.appliance:
|
|
||||||
<a href="${url('tempmon.appliances.view', uuid=probe.appliance.uuid)}">${probe.appliance}</a>
|
|
||||||
% endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if use_buefy:
|
<b-field horizontal label="Probe Location">
|
||||||
<b-field horizontal label="Probe Location">
|
<div>
|
||||||
<div>
|
${probe.location or ""}
|
||||||
${probe.location or ""}
|
</div>
|
||||||
</div>
|
</b-field>
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Probe Location</label>
|
|
||||||
<div class="field">${probe.location or ""}</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
% if use_buefy:
|
<b-field horizontal label="Showing">
|
||||||
<b-field horizontal label="Showing">
|
${time_range}
|
||||||
${time_range}
|
</b-field>
|
||||||
</b-field>
|
|
||||||
% else:
|
|
||||||
<div class="field-wrapper">
|
|
||||||
<label>Showing</label>
|
|
||||||
<div class="field">
|
|
||||||
${time_range}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -149,11 +57,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
% if use_buefy:
|
<canvas ref="tempchart" width="400" height="150"></canvas>
|
||||||
<canvas ref="tempchart" width="400" height="150"></canvas>
|
|
||||||
% else:
|
|
||||||
<canvas id="tempchart" width="400" height="150"></canvas>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="modify_this_page_vars()">
|
<%def name="modify_this_page_vars()">
|
||||||
|
|
|
@ -2,86 +2,48 @@
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="render_form_complete()">
|
<%def name="render_form_complete()">
|
||||||
% if use_buefy:
|
|
||||||
|
|
||||||
## ${self.render_form()}
|
## ${self.render_form()}
|
||||||
|
|
||||||
<script type="text/x-template" id="form-page-template">
|
<script type="text/x-template" id="form-page-template">
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between;">
|
<div style="display: flex; justify-content: space-between;">
|
||||||
|
|
||||||
<div class="form-wrapper">
|
<div class="form-wrapper">
|
||||||
|
|
||||||
<div style="display: flex; flex-direction: column;">
|
<div style="display: flex; flex-direction: column;">
|
||||||
|
|
||||||
<nav class="panel" id="probe-main">
|
<nav class="panel" id="probe-main">
|
||||||
<p class="panel-heading">General</p>
|
<p class="panel-heading">General</p>
|
||||||
<div class="panel-block">
|
<div class="panel-block">
|
||||||
<div>
|
<div>
|
||||||
${self.render_main_fields(form)}
|
${self.render_main_fields(form)}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div style="display: flex;">
|
|
||||||
<div class="panel-wrapper">
|
|
||||||
${self.left_column()}
|
|
||||||
</div>
|
|
||||||
<div class="panel-wrapper" style="margin-left: 1em;"> <!-- right column -->
|
|
||||||
${self.right_column()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div style="display: flex;">
|
||||||
|
<div class="panel-wrapper">
|
||||||
|
${self.left_column()}
|
||||||
|
</div>
|
||||||
|
<div class="panel-wrapper" style="margin-left: 1em;"> <!-- right column -->
|
||||||
|
${self.right_column()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul id="context-menu">
|
|
||||||
${self.context_menu_items()}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</script>
|
|
||||||
|
|
||||||
<div id="form-page-app">
|
|
||||||
<form-page></form-page>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
% else:
|
<ul id="context-menu">
|
||||||
## legacy / not buefy
|
${self.context_menu_items()}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between;">
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
<div class="form-wrapper">
|
<div id="form-page-app">
|
||||||
|
<form-page></form-page>
|
||||||
<div style="display: flex; flex-direction: column;">
|
</div>
|
||||||
|
|
||||||
<div class="panel" id="probe-main">
|
|
||||||
<h2>General</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
<div>
|
|
||||||
${self.render_main_fields(form)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="display: flex;">
|
|
||||||
<div class="panel-wrapper">
|
|
||||||
${self.left_column()}
|
|
||||||
</div>
|
|
||||||
<div class="panel-wrapper" style="margin-left: 1em;"> <!-- right column -->
|
|
||||||
${self.right_column()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul id="context-menu">
|
|
||||||
${self.context_menu_items()}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,43 +75,25 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="left_column()">
|
<%def name="left_column()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Temperatures</p>
|
||||||
<p class="panel-heading">Temperatures</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
<div>
|
||||||
<div>
|
${self.render_temperature_fields(form)}
|
||||||
${self.render_temperature_fields(form)}
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel">
|
|
||||||
<h2>Temperatures</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
${self.render_temperature_fields(form)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="right_column()">
|
<%def name="right_column()">
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Timeouts</p>
|
||||||
<p class="panel-heading">Timeouts</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
<div>
|
||||||
<div>
|
${self.render_timeout_fields(form)}
|
||||||
${self.render_timeout_fields(form)}
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="panel">
|
|
||||||
<h2>Timeouts</h2>
|
|
||||||
<div class="panel-body">
|
|
||||||
${self.render_timeout_fields(form)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</nav>
|
||||||
% endif
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_temperature_fields(form)">
|
<%def name="render_temperature_fields(form)">
|
||||||
|
|
|
@ -353,14 +353,10 @@
|
||||||
<div class="level">
|
<div class="level">
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
% if use_buefy:
|
<b-input name="entry"
|
||||||
<b-input name="entry"
|
placeholder="${quickie.placeholder}"
|
||||||
placeholder="${quickie.placeholder}"
|
autocomplete="off">
|
||||||
autocomplete="off">
|
</b-input>
|
||||||
</b-input>
|
|
||||||
% else:
|
|
||||||
${h.text('entry', placeholder=quickie.placeholder, autocomplete='off')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<button type="submit" class="button is-primary">
|
<button type="submit" class="button is-primary">
|
||||||
|
@ -706,54 +702,38 @@
|
||||||
% if show_prev_next is not Undefined and show_prev_next:
|
% if show_prev_next is not Undefined and show_prev_next:
|
||||||
% if prev_url:
|
% if prev_url:
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
% if use_buefy:
|
<b-button tag="a" href="${prev_url}"
|
||||||
<b-button tag="a" href="${prev_url}"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="arrow-left">
|
||||||
icon-left="arrow-left">
|
Older
|
||||||
Older
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.link_to(u"« Older", prev_url, class_='button autodisable')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
% if use_buefy:
|
<b-button tag="a" href="#"
|
||||||
<b-button tag="a" href="#"
|
disabled
|
||||||
disabled
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="arrow-left">
|
||||||
icon-left="arrow-left">
|
Older
|
||||||
Older
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.link_to(u"« Older", '#', class_='button', disabled='disabled')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
% if next_url:
|
% if next_url:
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
% if use_buefy:
|
<b-button tag="a" href="${next_url}"
|
||||||
<b-button tag="a" href="${next_url}"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="arrow-right">
|
||||||
icon-left="arrow-right">
|
Newer
|
||||||
Newer
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.link_to(u"Newer »", next_url, class_='button autodisable')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
% else:
|
% else:
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
% if use_buefy:
|
<b-button tag="a" href="#"
|
||||||
<b-button tag="a" href="#"
|
disabled
|
||||||
disabled
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="arrow-right">
|
||||||
icon-left="arrow-right">
|
Newer
|
||||||
Newer
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.link_to(u"Newer »", '#', class_='button', disabled='disabled')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -1,43 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/master/view.mako" />
|
<%inherit file="/master/view.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
|
||||||
${parent.extra_javascript()}
|
|
||||||
% if not use_buefy:
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
function show_packages(type) {
|
|
||||||
if (type == 'all') {
|
|
||||||
$('.showing .diffs').css('font-weight', 'normal');
|
|
||||||
$('table.diff tbody tr').show();
|
|
||||||
$('.showing .all').css('font-weight', 'bold');
|
|
||||||
} else if (type == 'diffs') {
|
|
||||||
$('.showing .all').css('font-weight', 'normal');
|
|
||||||
$('table.diff tbody tr:not(.diff)').hide();
|
|
||||||
$('.showing .diffs').css('font-weight', 'bold');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
|
||||||
|
|
||||||
show_packages('diffs');
|
|
||||||
|
|
||||||
$('.showing .all').click(function() {
|
|
||||||
show_packages('all');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.showing .diffs').click(function() {
|
|
||||||
show_packages('diffs')
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
% endif
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${parent.extra_styles()}
|
${parent.extra_styles()}
|
||||||
% if master.has_perm('execute'):
|
% if master.has_perm('execute'):
|
||||||
|
@ -132,7 +95,7 @@
|
||||||
% if instance_executable and master.has_perm('execute'):
|
% if instance_executable and master.has_perm('execute'):
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
% if instance.enabled and not instance.executing:
|
% if instance.enabled and not instance.executing:
|
||||||
% if use_buefy and expose_websockets:
|
% if expose_websockets:
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
icon-pack="fas"
|
icon-pack="fas"
|
||||||
icon-left="arrow-circle-right"
|
icon-left="arrow-circle-right"
|
||||||
|
@ -140,7 +103,7 @@
|
||||||
@click="$emit('execute-upgrade-click')">
|
@click="$emit('execute-upgrade-click')">
|
||||||
{{ upgradeExecuting ? "Working, please wait..." : "Execute this upgrade" }}
|
{{ upgradeExecuting ? "Working, please wait..." : "Execute this upgrade" }}
|
||||||
</b-button>
|
</b-button>
|
||||||
% elif use_buefy:
|
% else:
|
||||||
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), **{'@submit': 'submitForm'})}
|
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), **{'@submit': 'submitForm'})}
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
<b-button type="is-primary"
|
<b-button type="is-primary"
|
||||||
|
@ -151,11 +114,6 @@
|
||||||
{{ formSubmitting ? "Working, please wait..." : "Execute this upgrade" }}
|
{{ formSubmitting ? "Working, please wait..." : "Execute this upgrade" }}
|
||||||
</b-button>
|
</b-button>
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
% else:
|
|
||||||
${h.form(url('{}.execute'.format(route_prefix), uuid=instance.uuid), class_='autodisable')}
|
|
||||||
${h.csrf_token(request)}
|
|
||||||
${h.submit('execute', "Execute this upgrade", class_='button is-primary')}
|
|
||||||
${h.end_form()}
|
|
||||||
% endif
|
% endif
|
||||||
% elif instance.enabled:
|
% elif instance.enabled:
|
||||||
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is currently executing">Execute this upgrade</button>
|
<button type="button" class="button is-primary" disabled="disabled" title="This upgrade is currently executing">Execute this upgrade</button>
|
||||||
|
|
|
@ -2,43 +2,27 @@
|
||||||
|
|
||||||
<%def name="view_profile_button(person)">
|
<%def name="view_profile_button(person)">
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
% if use_buefy:
|
<b-button type="is-primary"
|
||||||
<b-button type="is-primary"
|
tag="a" href="${url('people.view_profile', uuid=person.uuid)}"
|
||||||
tag="a" href="${url('people.view_profile', uuid=person.uuid)}"
|
icon-pack="fas"
|
||||||
icon-pack="fas"
|
icon-left="user">
|
||||||
icon-left="user">
|
${person}
|
||||||
${person}
|
</b-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
|
||||||
${h.link_to(person, url('people.view_profile', uuid=person.uuid), class_='button is-primary')}
|
|
||||||
% endif
|
|
||||||
</div>
|
</div>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="view_profiles_helper(people)">
|
<%def name="view_profiles_helper(people)">
|
||||||
% if request.has_perm('people.view_profile'):
|
% if request.has_perm('people.view_profile'):
|
||||||
% if use_buefy:
|
<nav class="panel">
|
||||||
<nav class="panel">
|
<p class="panel-heading">Profiles</p>
|
||||||
<p class="panel-heading">Profiles</p>
|
<div class="panel-block">
|
||||||
<div class="panel-block">
|
<div style="display: flex; flex-direction: column;">
|
||||||
<div style="display: flex; flex-direction: column;">
|
<p class="block">View full profile for:</p>
|
||||||
<p class="block">View full profile for:</p>
|
% for person in people:
|
||||||
% for person in people:
|
${view_profile_button(person)}
|
||||||
${view_profile_button(person)}
|
% endfor
|
||||||
% endfor
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
% else:
|
|
||||||
<div class="object-helper">
|
|
||||||
<h3>Profiles</h3>
|
|
||||||
<div class="object-helper-content">
|
|
||||||
<p>View full profile for:</p>
|
|
||||||
% for person in people:
|
|
||||||
${view_profile_button(person)}
|
|
||||||
% endfor
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
% endif
|
</div>
|
||||||
|
</nav>
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
|
@ -24,11 +24,8 @@
|
||||||
Utilities
|
Utilities
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import six
|
|
||||||
import pytz
|
import pytz
|
||||||
import humanize
|
import humanize
|
||||||
import logging
|
import logging
|
||||||
|
@ -198,26 +195,6 @@ def get_liburl(request, key, fallback=True):
|
||||||
return 'https://code.jquery.com/ui/{}/themes/dark-hive/jquery-ui.css'.format(version)
|
return 'https://code.jquery.com/ui/{}/themes/dark-hive/jquery-ui.css'.format(version)
|
||||||
|
|
||||||
|
|
||||||
def should_use_buefy(request):
|
|
||||||
"""
|
|
||||||
Returns a flag indicating whether or not the current theme supports (and
|
|
||||||
therefore should use) the Buefy JS library.
|
|
||||||
"""
|
|
||||||
# first check theme-specific setting, if one has been defined
|
|
||||||
theme = request.registry.settings['tailbone.theme']
|
|
||||||
buefy = request.rattail_config.getbool('tailbone', 'themes.{}.use_buefy'.format(theme))
|
|
||||||
if buefy is not None:
|
|
||||||
return buefy
|
|
||||||
|
|
||||||
# TODO: should not hard-code this surely, but works for now...
|
|
||||||
if theme == 'falafel':
|
|
||||||
return True
|
|
||||||
|
|
||||||
# TODO: probably should not use this fallback? it was the first setting
|
|
||||||
# i tested with, but is poorly named to say the least
|
|
||||||
return request.rattail_config.getbool('tailbone', 'grids.use_buefy', default=False)
|
|
||||||
|
|
||||||
|
|
||||||
def pretty_datetime(config, value):
|
def pretty_datetime(config, value):
|
||||||
"""
|
"""
|
||||||
Formats a datetime as a "pretty" human-readable string, with a tooltip
|
Formats a datetime as a "pretty" human-readable string, with a tooltip
|
||||||
|
@ -284,7 +261,7 @@ def raw_datetime(config, value, verbose=False, as_date=False):
|
||||||
else:
|
else:
|
||||||
kwargs['c'] = value.strftime('%Y-%m-%d %I:%M:%S %p')
|
kwargs['c'] = value.strftime('%Y-%m-%d %I:%M:%S %p')
|
||||||
else:
|
else:
|
||||||
kwargs['c'] = six.text_type(value)
|
kwargs['c'] = str(value)
|
||||||
|
|
||||||
time_diff = app.render_time_ago(time_ago, fallback=None)
|
time_diff = app.render_time_ago(time_ago, fallback=None)
|
||||||
if time_diff is not None:
|
if time_diff is not None:
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,8 +24,6 @@
|
||||||
Auth Views
|
Auth Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
from rattail.db.auth import authenticate_user, set_user_password
|
from rattail.db.auth import authenticate_user, set_user_password
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
|
@ -101,9 +99,7 @@ class AuthenticationView(View):
|
||||||
self.request.session.flash("{} is already logged in".format(self.request.user), 'error')
|
self.request.session.flash("{} is already logged in".format(self.request.user), 'error')
|
||||||
return self.redirect(referrer)
|
return self.redirect(referrer)
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
form = forms.Form(schema=UserLogin(), request=self.request)
|
||||||
form = forms.Form(schema=UserLogin(), request=self.request,
|
|
||||||
use_buefy=use_buefy)
|
|
||||||
form.save_label = "Login"
|
form.save_label = "Login"
|
||||||
form.auto_disable_save = False
|
form.auto_disable_save = False
|
||||||
form.auto_disable = False # TODO: deprecate / remove this
|
form.auto_disable = False # TODO: deprecate / remove this
|
||||||
|
@ -126,16 +122,13 @@ class AuthenticationView(View):
|
||||||
'tailbone', 'main_image_url',
|
'tailbone', 'main_image_url',
|
||||||
default=self.request.static_url('tailbone:static/img/home_logo.png'))
|
default=self.request.static_url('tailbone:static/img/home_logo.png'))
|
||||||
|
|
||||||
context = {
|
return {
|
||||||
'form': form,
|
'form': form,
|
||||||
'referrer': referrer,
|
'referrer': referrer,
|
||||||
'image_url': image_url,
|
'image_url': image_url,
|
||||||
'use_buefy': use_buefy,
|
'index_title': self.rattail_config.node_title(),
|
||||||
'help_url': global_help_url(self.rattail_config),
|
'help_url': global_help_url(self.rattail_config),
|
||||||
}
|
}
|
||||||
if use_buefy:
|
|
||||||
context['index_title'] = self.rattail_config.node_title()
|
|
||||||
return context
|
|
||||||
|
|
||||||
def authenticate_user(self, username, password):
|
def authenticate_user(self, username, password):
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
|
@ -177,15 +170,14 @@ class AuthenticationView(View):
|
||||||
self.request.session.flash("Cannot change password for user: {}".format(self.request.user))
|
self.request.session.flash("Cannot change password for user: {}".format(self.request.user))
|
||||||
return self.redirect(self.request.get_referrer())
|
return self.redirect(self.request.get_referrer())
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
schema = ChangePassword().bind(user=self.request.user, request=self.request)
|
schema = ChangePassword().bind(user=self.request.user, request=self.request)
|
||||||
form = forms.Form(schema=schema, request=self.request, use_buefy=use_buefy)
|
form = forms.Form(schema=schema, request=self.request)
|
||||||
if form.validate(newstyle=True):
|
if form.validate(newstyle=True):
|
||||||
set_user_password(self.request.user, form.validated['new_password'])
|
set_user_password(self.request.user, form.validated['new_password'])
|
||||||
self.request.session.flash("Your password has been changed.")
|
self.request.session.flash("Your password has been changed.")
|
||||||
return self.redirect(self.request.get_referrer())
|
return self.redirect(self.request.get_referrer())
|
||||||
|
|
||||||
return {'form': form, 'use_buefy': use_buefy}
|
return {'form': form}
|
||||||
|
|
||||||
def become_root(self):
|
def become_root(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
Base views for maintaining "new-style" batches.
|
Base views for maintaining "new-style" batches.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
@ -37,7 +35,6 @@ import tempfile
|
||||||
from six import StringIO
|
from six import StringIO
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import six
|
|
||||||
import markdown
|
import markdown
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
@ -172,7 +169,6 @@ class BatchMasterView(MasterView):
|
||||||
|
|
||||||
def template_kwargs_view(self, **kwargs):
|
def template_kwargs_view(self, **kwargs):
|
||||||
kwargs = super(BatchMasterView, self).template_kwargs_view(**kwargs)
|
kwargs = super(BatchMasterView, self).template_kwargs_view(**kwargs)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
batch = kwargs['instance']
|
batch = kwargs['instance']
|
||||||
kwargs['batch'] = batch
|
kwargs['batch'] = batch
|
||||||
kwargs['handler'] = self.handler
|
kwargs['handler'] = self.handler
|
||||||
|
@ -194,30 +190,22 @@ class BatchMasterView(MasterView):
|
||||||
|
|
||||||
breakdown = self.make_status_breakdown(batch)
|
breakdown = self.make_status_breakdown(batch)
|
||||||
|
|
||||||
if use_buefy:
|
factory = self.get_grid_factory()
|
||||||
factory = self.get_grid_factory()
|
g = factory('batch_row_status_breakdown', [],
|
||||||
g = factory('batch_row_status_breakdown', [],
|
columns=['title', 'count'])
|
||||||
columns=['title', 'count'])
|
g.set_click_handler('title', "autoFilterStatus(props.row)")
|
||||||
g.set_click_handler('title', "autoFilterStatus(props.row)")
|
kwargs['status_breakdown_data'] = breakdown
|
||||||
kwargs['status_breakdown_data'] = breakdown
|
kwargs['status_breakdown_grid'] = HTML.literal(
|
||||||
kwargs['status_breakdown_grid'] = HTML.literal(
|
g.render_buefy_table_element(data_prop='statusBreakdownData',
|
||||||
g.render_buefy_table_element(data_prop='statusBreakdownData',
|
empty_labels=True))
|
||||||
empty_labels=True))
|
|
||||||
|
|
||||||
else:
|
|
||||||
kwargs['status_breakdown'] = [
|
|
||||||
(status['title'], status['count'])
|
|
||||||
for status in breakdown]
|
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def make_upload_worksheet_form(self, batch):
|
def make_upload_worksheet_form(self, batch):
|
||||||
action_url = self.get_action_url('upload_worksheet', batch)
|
action_url = self.get_action_url('upload_worksheet', batch)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
form = forms.Form(schema=UploadWorksheet(),
|
form = forms.Form(schema=UploadWorksheet(),
|
||||||
request=self.request,
|
request=self.request,
|
||||||
action_url=action_url,
|
action_url=action_url,
|
||||||
use_buefy=use_buefy,
|
|
||||||
component='upload-worksheet-form')
|
component='upload-worksheet-form')
|
||||||
form.set_type('worksheet_file', 'file')
|
form.set_type('worksheet_file', 'file')
|
||||||
# TODO: must set these to avoid some default Buefy code
|
# TODO: must set these to avoid some default Buefy code
|
||||||
|
@ -431,7 +419,6 @@ class BatchMasterView(MasterView):
|
||||||
return dict(batch.params or {})
|
return dict(batch.params or {})
|
||||||
|
|
||||||
def render_complete(self, batch, field):
|
def render_complete(self, batch, field):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
text = "Yes" if batch.complete else "No"
|
text = "Yes" if batch.complete else "No"
|
||||||
|
|
||||||
if batch.executed or not self.has_perm('edit'):
|
if batch.executed or not self.has_perm('edit'):
|
||||||
|
@ -446,18 +433,13 @@ class BatchMasterView(MasterView):
|
||||||
|
|
||||||
url = self.get_action_url('toggle_complete', batch)
|
url = self.get_action_url('toggle_complete', batch)
|
||||||
kwargs = {'@submit': 'togglingBatchComplete = true'}
|
kwargs = {'@submit': 'togglingBatchComplete = true'}
|
||||||
if not use_buefy:
|
|
||||||
kwargs['class_'] = 'autodisable'
|
|
||||||
begin_form = tags.form(url, **kwargs)
|
begin_form = tags.form(url, **kwargs)
|
||||||
|
|
||||||
if use_buefy:
|
label = HTML.literal(
|
||||||
label = HTML.literal(
|
'{{{{ togglingBatchComplete ? "Working, please wait..." : "{}" }}}}'.format(label))
|
||||||
'{{{{ togglingBatchComplete ? "Working, please wait..." : "{}" }}}}'.format(label))
|
submit = self.make_buefy_button(label, is_primary=True,
|
||||||
submit = self.make_buefy_button(label, is_primary=True,
|
native_type='submit',
|
||||||
native_type='submit',
|
**{':disabled': 'togglingBatchComplete'})
|
||||||
**{':disabled': 'togglingBatchComplete'})
|
|
||||||
else:
|
|
||||||
submit = tags.submit('submit', label)
|
|
||||||
|
|
||||||
form = [
|
form = [
|
||||||
begin_form,
|
begin_form,
|
||||||
|
@ -467,23 +449,16 @@ class BatchMasterView(MasterView):
|
||||||
tags.end_form(),
|
tags.end_form(),
|
||||||
]
|
]
|
||||||
|
|
||||||
if use_buefy:
|
text = HTML.tag('div', class_='control', c=text)
|
||||||
text = HTML.tag('div', class_='control', c=text)
|
form = HTML.tag('div', class_='control', c=form)
|
||||||
form = HTML.tag('div', class_='control', c=form)
|
content = [
|
||||||
content = [
|
HTML.tag('nav', class_='level',
|
||||||
HTML.tag('nav', class_='level',
|
c=[HTML.tag('div', class_='level-left', c=[
|
||||||
c=[HTML.tag('div', class_='level-left', c=[
|
text,
|
||||||
text,
|
HTML.literal(' '),
|
||||||
HTML.literal(' '),
|
form,
|
||||||
form,
|
])]),
|
||||||
])]),
|
]
|
||||||
]
|
|
||||||
|
|
||||||
else:
|
|
||||||
content = [
|
|
||||||
text,
|
|
||||||
HTML.literal(' '),
|
|
||||||
] + form
|
|
||||||
|
|
||||||
return HTML.tag('div', c=content)
|
return HTML.tag('div', c=content)
|
||||||
|
|
||||||
|
@ -491,7 +466,7 @@ class BatchMasterView(MasterView):
|
||||||
user = getattr(batch, field)
|
user = getattr(batch, field)
|
||||||
if not user:
|
if not user:
|
||||||
return ""
|
return ""
|
||||||
title = six.text_type(user)
|
title = str(user)
|
||||||
url = self.request.route_url('users.view', uuid=user.uuid)
|
url = self.request.route_url('users.view', uuid=user.uuid)
|
||||||
return tags.link_to(title, url)
|
return tags.link_to(title, url)
|
||||||
|
|
||||||
|
@ -513,7 +488,7 @@ class BatchMasterView(MasterView):
|
||||||
|
|
||||||
# TODO: this needs work yet surely...why is this an issue?
|
# TODO: this needs work yet surely...why is this an issue?
|
||||||
# treat 'filename' field specially, for some reason it can be a filedict?
|
# treat 'filename' field specially, for some reason it can be a filedict?
|
||||||
if 'filename' in kwargs and not isinstance(kwargs['filename'], six.string_types):
|
if 'filename' in kwargs and not isinstance(kwargs['filename'], str):
|
||||||
kwargs['filename'] = '' # null not allowed
|
kwargs['filename'] = '' # null not allowed
|
||||||
|
|
||||||
# TODO: is this still necessary with colander?
|
# TODO: is this still necessary with colander?
|
||||||
|
@ -533,7 +508,7 @@ class BatchMasterView(MasterView):
|
||||||
os.remove(upload['temp_path'])
|
os.remove(upload['temp_path'])
|
||||||
os.rmdir(upload['tempdir'])
|
os.rmdir(upload['tempdir'])
|
||||||
|
|
||||||
for key, upload in six.iteritems(uploads):
|
for key, upload in uploads.items():
|
||||||
if isinstance(upload, dict):
|
if isinstance(upload, dict):
|
||||||
process(upload, key)
|
process(upload, key)
|
||||||
else:
|
else:
|
||||||
|
@ -657,7 +632,7 @@ class BatchMasterView(MasterView):
|
||||||
code = row.status_code
|
code = row.status_code
|
||||||
if code is None:
|
if code is None:
|
||||||
return ""
|
return ""
|
||||||
text = self.get_row_status_enum().get(code, six.text_type(code))
|
text = self.get_row_status_enum().get(code, str(code))
|
||||||
if row.status_text:
|
if row.status_text:
|
||||||
return HTML.tag('span', title=row.status_text, c=text)
|
return HTML.tag('span', title=row.status_text, c=text)
|
||||||
return text
|
return text
|
||||||
|
@ -707,21 +682,12 @@ class BatchMasterView(MasterView):
|
||||||
permission_prefix = self.get_permission_prefix()
|
permission_prefix = self.get_permission_prefix()
|
||||||
if self.request.has_perm('{}.create_row'.format(permission_prefix)):
|
if self.request.has_perm('{}.create_row'.format(permission_prefix)):
|
||||||
url = self.get_action_url('create_row', batch)
|
url = self.get_action_url('create_row', batch)
|
||||||
if self.get_use_buefy():
|
return self.make_buefy_button("New Row", url=url,
|
||||||
return self.make_buefy_button("New Row", url=url,
|
is_primary=True,
|
||||||
is_primary=True,
|
icon_left='plus')
|
||||||
icon_left='plus')
|
|
||||||
else:
|
|
||||||
text = "Create a new {}".format(self.get_row_model_title())
|
|
||||||
link = tags.link_to(text, url)
|
|
||||||
return HTML.tag('p', c=[link])
|
|
||||||
|
|
||||||
def make_batch_row_grid_tools(self, batch):
|
def make_batch_row_grid_tools(self, batch):
|
||||||
if self.get_use_buefy():
|
pass
|
||||||
return
|
|
||||||
if self.rows_bulk_deletable and not batch.executed and self.request.has_perm('{}.delete_rows'.format(self.get_permission_prefix())):
|
|
||||||
url = self.request.route_url('{}.delete_rows'.format(self.get_route_prefix()), uuid=batch.uuid)
|
|
||||||
return HTML.tag('p', c=[tags.link_to("Delete all rows matching current search", url)])
|
|
||||||
|
|
||||||
def make_row_grid_kwargs(self, **kwargs):
|
def make_row_grid_kwargs(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -733,21 +699,19 @@ class BatchMasterView(MasterView):
|
||||||
# TODO: most of this logic is copied from MasterView, should refactor/merge somehow...
|
# TODO: most of this logic is copied from MasterView, should refactor/merge somehow...
|
||||||
if 'main_actions' not in kwargs:
|
if 'main_actions' not in kwargs:
|
||||||
actions = []
|
actions = []
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# view action
|
# view action
|
||||||
if self.rows_viewable:
|
if self.rows_viewable:
|
||||||
view = lambda r, i: self.get_row_action_url('view', r)
|
view = lambda r, i: self.get_row_action_url('view', r)
|
||||||
icon = 'eye' if use_buefy else 'zoomin'
|
actions.append(self.make_action('view', icon='eye', url=view))
|
||||||
actions.append(self.make_action('view', icon=icon, url=view))
|
|
||||||
|
|
||||||
# edit and delete are NOT allowed after execution, or if batch is "complete"
|
# edit and delete are NOT allowed after execution, or if batch is "complete"
|
||||||
if not batch.executed and not batch.complete:
|
if not batch.executed and not batch.complete:
|
||||||
|
|
||||||
# edit action
|
# edit action
|
||||||
if self.rows_editable and self.has_perm('edit_row'):
|
if self.rows_editable and self.has_perm('edit_row'):
|
||||||
icon = 'edit' if use_buefy else 'pencil'
|
actions.append(self.make_action('edit', icon='edit',
|
||||||
actions.append(self.make_action('edit', icon=icon, url=self.row_edit_action_url))
|
url=self.row_edit_action_url))
|
||||||
|
|
||||||
# delete action
|
# delete action
|
||||||
if self.rows_deletable and self.has_perm('delete_row'):
|
if self.rows_deletable and self.has_perm('delete_row'):
|
||||||
|
@ -793,7 +757,7 @@ class BatchMasterView(MasterView):
|
||||||
# nb. must make new session, separate from main thread
|
# nb. must make new session, separate from main thread
|
||||||
session = app.make_session()
|
session = app.make_session()
|
||||||
batch = self.get_instance_for_key(key, session)
|
batch = self.get_instance_for_key(key, session)
|
||||||
batch_str = six.text_type(batch)
|
batch_str = str(batch)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# try to delete batch
|
# try to delete batch
|
||||||
|
@ -869,7 +833,6 @@ class BatchMasterView(MasterView):
|
||||||
"""
|
"""
|
||||||
defaults = {}
|
defaults = {}
|
||||||
route_prefix = self.get_route_prefix()
|
route_prefix = self.get_route_prefix()
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
schema = None
|
schema = None
|
||||||
if self.has_execution_options(batch):
|
if self.has_execution_options(batch):
|
||||||
|
@ -891,13 +854,12 @@ class BatchMasterView(MasterView):
|
||||||
labels[field.name] = field.title
|
labels[field.name] = field.title
|
||||||
|
|
||||||
# auto-convert select widgets for buefy theme
|
# auto-convert select widgets for buefy theme
|
||||||
if use_buefy and isinstance(field.widget, forms.widgets.PlainSelectWidget):
|
if isinstance(field.widget, forms.widgets.PlainSelectWidget):
|
||||||
field.widget = dfwidget.SelectWidget(values=field.widget.values)
|
field.widget = dfwidget.SelectWidget(values=field.widget.values)
|
||||||
|
|
||||||
if not schema:
|
if not schema:
|
||||||
schema = colander.Schema()
|
schema = colander.Schema()
|
||||||
|
|
||||||
kwargs['use_buefy'] = use_buefy
|
|
||||||
kwargs['component'] = 'execute-form'
|
kwargs['component'] = 'execute-form'
|
||||||
form = forms.Form(schema=schema, request=self.request, defaults=defaults, **kwargs)
|
form = forms.Form(schema=schema, request=self.request, defaults=defaults, **kwargs)
|
||||||
self.configure_execute_form(form)
|
self.configure_execute_form(form)
|
||||||
|
@ -1051,8 +1013,7 @@ class BatchMasterView(MasterView):
|
||||||
data = json.dumps({
|
data = json.dumps({
|
||||||
'everything_complete': True,
|
'everything_complete': True,
|
||||||
})
|
})
|
||||||
if six.PY3:
|
data = data.encode('utf_8')
|
||||||
data = data.encode('utf_8')
|
|
||||||
cxn.send(data)
|
cxn.send(data)
|
||||||
cxn.send(suffix)
|
cxn.send(suffix)
|
||||||
cxn.close()
|
cxn.close()
|
||||||
|
@ -1061,7 +1022,7 @@ class BatchMasterView(MasterView):
|
||||||
with short_session() as s:
|
with short_session() as s:
|
||||||
batch = s.query(self.model_class).get(batch_uuid)
|
batch = s.query(self.model_class).get(batch_uuid)
|
||||||
batch_id = batch.id_str
|
batch_id = batch.id_str
|
||||||
description = six.text_type(batch)
|
description = str(batch)
|
||||||
|
|
||||||
self.launch_subprocess(
|
self.launch_subprocess(
|
||||||
port=port, username=username,
|
port=port, username=username,
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
Views for importer batches
|
Views for importer batches
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
@ -139,7 +137,6 @@ class ImporterBatchView(BatchMasterView):
|
||||||
|
|
||||||
def configure_row_grid(self, g):
|
def configure_row_grid(self, g):
|
||||||
super(ImporterBatchView, self).configure_row_grid(g)
|
super(ImporterBatchView, self).configure_row_grid(g)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
def make_filter(field, **kwargs):
|
def make_filter(field, **kwargs):
|
||||||
column = getattr(self.current_row_table.c, field)
|
column = getattr(self.current_row_table.c, field)
|
||||||
|
@ -150,11 +147,8 @@ class ImporterBatchView(BatchMasterView):
|
||||||
|
|
||||||
# for some reason we have to do this differently for Buefy?
|
# for some reason we have to do this differently for Buefy?
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if not use_buefy:
|
|
||||||
kwargs['value_enum'] = self.enum.IMPORTER_BATCH_ROW_STATUS
|
|
||||||
make_filter('status_code', label="Status", **kwargs)
|
make_filter('status_code', label="Status", **kwargs)
|
||||||
if use_buefy:
|
g.filters['status_code'].set_choices(self.enum.IMPORTER_BATCH_ROW_STATUS)
|
||||||
g.filters['status_code'].set_choices(self.enum.IMPORTER_BATCH_ROW_STATUS)
|
|
||||||
|
|
||||||
def make_sorter(field):
|
def make_sorter(field):
|
||||||
column = getattr(self.current_row_table.c, field)
|
column = getattr(self.current_row_table.c, field)
|
||||||
|
|
|
@ -24,14 +24,10 @@
|
||||||
Views for inventory batches
|
Views for inventory batches
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import decimal
|
import decimal
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from rattail import pod
|
from rattail import pod
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.db.util import make_full_description
|
from rattail.db.util import make_full_description
|
||||||
|
@ -234,9 +230,8 @@ class InventoryBatchView(BatchMasterView):
|
||||||
if batch.executed:
|
if batch.executed:
|
||||||
return self.redirect(self.get_action_url('view', batch))
|
return self.redirect(self.get_action_url('view', batch))
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
schema = DesktopForm().bind(session=self.Session())
|
schema = DesktopForm().bind(session=self.Session())
|
||||||
form = forms.Form(schema=schema, request=self.request, use_buefy=use_buefy)
|
form = forms.Form(schema=schema, request=self.request)
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
if form.validate(newstyle=True):
|
if form.validate(newstyle=True):
|
||||||
|
|
||||||
|
@ -273,7 +268,7 @@ class InventoryBatchView(BatchMasterView):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
dform = form.make_deform_form()
|
dform = form.make_deform_form()
|
||||||
msg = "Form did not validate: {}".format(six.text_type(dform.error))
|
msg = "Form did not validate: {}".format(str(dform.error))
|
||||||
self.request.session.flash(msg, 'error')
|
self.request.session.flash(msg, 'error')
|
||||||
|
|
||||||
title = self.get_instance_title(batch)
|
title = self.get_instance_title(batch)
|
||||||
|
@ -345,7 +340,7 @@ class InventoryBatchView(BatchMasterView):
|
||||||
upc = re.sub(r'\D', '', entry.strip())
|
upc = re.sub(r'\D', '', entry.strip())
|
||||||
if upc:
|
if upc:
|
||||||
upc = GPC(upc)
|
upc = GPC(upc)
|
||||||
result['upc'] = six.text_type(upc)
|
result['upc'] = str(upc)
|
||||||
result['upc_pretty'] = upc.pretty()
|
result['upc_pretty'] = upc.pretty()
|
||||||
result['image_url'] = pod.get_image_url(self.rattail_config, upc)
|
result['image_url'] = pod.get_image_url(self.rattail_config, upc)
|
||||||
|
|
||||||
|
@ -374,10 +369,10 @@ class InventoryBatchView(BatchMasterView):
|
||||||
data = {}
|
data = {}
|
||||||
if product and (not product.deleted or self.request.has_perm('products.view_deleted')):
|
if product and (not product.deleted or self.request.has_perm('products.view_deleted')):
|
||||||
data['uuid'] = product.uuid
|
data['uuid'] = product.uuid
|
||||||
data['upc'] = six.text_type(product.upc)
|
data['upc'] = str(product.upc)
|
||||||
data['upc_pretty'] = product.upc.pretty()
|
data['upc_pretty'] = product.upc.pretty()
|
||||||
data['full_description'] = product.full_description
|
data['full_description'] = product.full_description
|
||||||
data['brand_name'] = six.text_type(product.brand or '')
|
data['brand_name'] = str(product.brand or '')
|
||||||
data['description'] = product.description
|
data['description'] = product.description
|
||||||
data['size'] = product.size
|
data['size'] = product.size
|
||||||
data['case_quantity'] = 1 # default
|
data['case_quantity'] = 1 # default
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,12 +24,8 @@
|
||||||
Views for maintaining vendor catalogs
|
Views for maintaining vendor catalogs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
|
@ -196,9 +192,6 @@ class VendorCatalogView(FileBatchMasterView):
|
||||||
values = [(p.key, p.display) for p in parsers]
|
values = [(p.key, p.display) for p in parsers]
|
||||||
if len(values) == 1:
|
if len(values) == 1:
|
||||||
f.set_default('parser_key', parsers[0].key)
|
f.set_default('parser_key', parsers[0].key)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
if not use_buefy:
|
|
||||||
values.insert(0, ('', "(please choose)"))
|
|
||||||
f.set_widget('parser_key', dfwidget.SelectWidget(values=values))
|
f.set_widget('parser_key', dfwidget.SelectWidget(values=values))
|
||||||
else:
|
else:
|
||||||
f.set_readonly('parser_key')
|
f.set_readonly('parser_key')
|
||||||
|
@ -235,7 +228,7 @@ class VendorCatalogView(FileBatchMasterView):
|
||||||
vendor = self.Session.query(model.Vendor).get(
|
vendor = self.Session.query(model.Vendor).get(
|
||||||
self.request.POST['vendor_uuid'])
|
self.request.POST['vendor_uuid'])
|
||||||
if vendor:
|
if vendor:
|
||||||
vendor_display = six.text_type(vendor)
|
vendor_display = str(vendor)
|
||||||
f.set_widget('vendor_uuid',
|
f.set_widget('vendor_uuid',
|
||||||
forms.widgets.JQueryAutocompleteWidget(
|
forms.widgets.JQueryAutocompleteWidget(
|
||||||
field_display=vendor_display,
|
field_display=vendor_display,
|
||||||
|
@ -275,35 +268,20 @@ class VendorCatalogView(FileBatchMasterView):
|
||||||
return parser.display
|
return parser.display
|
||||||
|
|
||||||
def template_kwargs_create(self, **kwargs):
|
def template_kwargs_create(self, **kwargs):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
vendor_handler = app.get_vendor_handler()
|
vendor_handler = app.get_vendor_handler()
|
||||||
parsers = self.get_parsers()
|
parsers = self.get_parsers()
|
||||||
parsers_data = {}
|
parsers_data = {}
|
||||||
for parser in parsers:
|
for parser in parsers:
|
||||||
if use_buefy:
|
pdata = {'key': parser.key,
|
||||||
pdata = {'key': parser.key,
|
'vendor_key': parser.vendor_key}
|
||||||
'vendor_key': parser.vendor_key}
|
if parser.vendor_key:
|
||||||
if parser.vendor_key:
|
vendor = vendor_handler.get_vendor(self.Session(),
|
||||||
vendor = vendor_handler.get_vendor(self.Session(),
|
parser.vendor_key)
|
||||||
parser.vendor_key)
|
if vendor:
|
||||||
if vendor:
|
pdata['vendor_uuid'] = vendor.uuid
|
||||||
pdata['vendor_uuid'] = vendor.uuid
|
pdata['vendor_name'] = vendor.name
|
||||||
pdata['vendor_name'] = vendor.name
|
parsers_data[parser.key] = pdata
|
||||||
parsers_data[parser.key] = pdata
|
|
||||||
else:
|
|
||||||
if parser.vendor_key:
|
|
||||||
vendor = vendor_handler.get_vendor(self.Session(),
|
|
||||||
parser.vendor_key)
|
|
||||||
if vendor:
|
|
||||||
parser.vendormap_value = "{{uuid: '{}', name: '{}'}}".format(
|
|
||||||
vendor.uuid, vendor.name.replace("'", "\\'"))
|
|
||||||
else:
|
|
||||||
log.warning("vendor '{}' not found for parser: {}".format(
|
|
||||||
parser.vendor_key, parser.key))
|
|
||||||
parser.vendormap_value = 'null'
|
|
||||||
else:
|
|
||||||
parser.vendormap_value = 'null'
|
|
||||||
kwargs['parsers'] = parsers
|
kwargs['parsers'] = parsers
|
||||||
kwargs['parsers_data'] = parsers_data
|
kwargs['parsers_data'] = parsers_data
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,10 +24,7 @@
|
||||||
Various common views
|
Various common views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import six
|
|
||||||
|
|
||||||
from rattail.batch import consume_batch_id
|
from rattail.batch import consume_batch_id
|
||||||
from rattail.util import OrderedDict, simple_error, import_module_path
|
from rattail.util import OrderedDict, simple_error, import_module_path
|
||||||
|
@ -62,14 +59,11 @@ class CommonView(View):
|
||||||
'tailbone', 'main_image_url',
|
'tailbone', 'main_image_url',
|
||||||
default=self.request.static_url('tailbone:static/img/home_logo.png'))
|
default=self.request.static_url('tailbone:static/img/home_logo.png'))
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
context = {
|
context = {
|
||||||
'image_url': image_url,
|
'image_url': image_url,
|
||||||
'use_buefy': use_buefy,
|
'index_title': self.rattail_config.node_title(),
|
||||||
'help_url': global_help_url(self.rattail_config),
|
'help_url': global_help_url(self.rattail_config),
|
||||||
}
|
}
|
||||||
if use_buefy:
|
|
||||||
context['index_title'] = self.rattail_config.node_title()
|
|
||||||
|
|
||||||
if self.expose_quickie_search:
|
if self.expose_quickie_search:
|
||||||
context['quickie'] = self.get_quickie_context()
|
context['quickie'] = self.get_quickie_context()
|
||||||
|
@ -83,12 +77,8 @@ class CommonView(View):
|
||||||
with open(self.robots_txt_path, 'rt') as f:
|
with open(self.robots_txt_path, 'rt') as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
response = self.request.response
|
response = self.request.response
|
||||||
if six.PY3:
|
response.text = content
|
||||||
response.text = content
|
response.content_type = 'text/plain'
|
||||||
response.content_type = 'text/plain'
|
|
||||||
else:
|
|
||||||
response.body = content
|
|
||||||
response.content_type = b'text/plain'
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def get_project_title(self):
|
def get_project_title(self):
|
||||||
|
@ -114,16 +104,12 @@ class CommonView(View):
|
||||||
"""
|
"""
|
||||||
Generic view to show "about project" info page.
|
Generic view to show "about project" info page.
|
||||||
"""
|
"""
|
||||||
use_buefy = self.get_use_buefy()
|
return {
|
||||||
context = {
|
|
||||||
'project_title': self.get_project_title(),
|
'project_title': self.get_project_title(),
|
||||||
'project_version': self.get_project_version(),
|
'project_version': self.get_project_version(),
|
||||||
'packages': self.get_packages(),
|
'packages': self.get_packages(),
|
||||||
'use_buefy': use_buefy,
|
'index_title': self.rattail_config.node_title(),
|
||||||
}
|
}
|
||||||
if use_buefy:
|
|
||||||
context['index_title'] = self.rattail_config.node_title()
|
|
||||||
return context
|
|
||||||
|
|
||||||
def get_packages(self):
|
def get_packages(self):
|
||||||
"""
|
"""
|
||||||
|
@ -203,7 +189,6 @@ class CommonView(View):
|
||||||
if not self.request.is_root:
|
if not self.request.is_root:
|
||||||
raise self.forbidden()
|
raise self.forbidden()
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
app_title = self.rattail_config.app_title()
|
app_title = self.rattail_config.app_title()
|
||||||
poser_handler = app.get_poser_handler()
|
poser_handler = app.get_poser_handler()
|
||||||
|
@ -253,7 +238,6 @@ class CommonView(View):
|
||||||
poser_error = simple_error(error)
|
poser_error = simple_error(error)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'use_buefy': use_buefy,
|
|
||||||
'app_title': app_title,
|
'app_title': app_title,
|
||||||
'index_title': app_title,
|
'index_title': app_title,
|
||||||
'poser_dir': poser_dir,
|
'poser_dir': poser_dir,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,12 +24,8 @@
|
||||||
Base View Class
|
Base View Class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.core import Object
|
from rattail.core import Object
|
||||||
from rattail.util import progress_loop
|
from rattail.util import progress_loop
|
||||||
|
@ -41,7 +37,6 @@ from pyramid.response import FileResponse
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.auth import logout_user
|
from tailbone.auth import logout_user
|
||||||
from tailbone.progress import SessionProgress
|
from tailbone.progress import SessionProgress
|
||||||
from tailbone.util import should_use_buefy
|
|
||||||
from tailbone.config import protected_usernames
|
from tailbone.config import protected_usernames
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,13 +89,6 @@ class View(object):
|
||||||
def notfound(self):
|
def notfound(self):
|
||||||
return httpexceptions.HTTPNotFound()
|
return httpexceptions.HTTPNotFound()
|
||||||
|
|
||||||
def get_use_buefy(self):
|
|
||||||
"""
|
|
||||||
Returns a flag indicating whether or not the current theme supports
|
|
||||||
(and therefore should use) the Buefy JS library.
|
|
||||||
"""
|
|
||||||
return should_use_buefy(self.request)
|
|
||||||
|
|
||||||
def late_login_user(self):
|
def late_login_user(self):
|
||||||
"""
|
"""
|
||||||
Returns the :class:`rattail:rattail.db.model.User` instance
|
Returns the :class:`rattail:rattail.db.model.User` instance
|
||||||
|
@ -170,8 +158,6 @@ class View(object):
|
||||||
if attachment:
|
if attachment:
|
||||||
if not filename:
|
if not filename:
|
||||||
filename = os.path.basename(path)
|
filename = os.path.basename(path)
|
||||||
if six.PY2:
|
|
||||||
filename = filename.encode('ascii', 'replace')
|
|
||||||
response.content_disposition = str('attachment; filename="{}"'.format(filename))
|
response.content_disposition = str('attachment; filename="{}"'.format(filename))
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,9 +24,6 @@
|
||||||
Customer Views
|
Customer Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import six
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
|
@ -205,7 +202,6 @@ class CustomerView(MasterView):
|
||||||
super(CustomerView, self).configure_common_form(f)
|
super(CustomerView, self).configure_common_form(f)
|
||||||
customer = f.model_instance
|
customer = f.model_instance
|
||||||
permission_prefix = self.get_permission_prefix()
|
permission_prefix = self.get_permission_prefix()
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
f.set_renderer('default_email', self.render_default_email)
|
f.set_renderer('default_email', self.render_default_email)
|
||||||
if not self.creating and customer.emails:
|
if not self.creating and customer.emails:
|
||||||
|
@ -251,12 +247,7 @@ class CustomerView(MasterView):
|
||||||
|
|
||||||
# people
|
# people
|
||||||
if self.viewing:
|
if self.viewing:
|
||||||
if use_buefy:
|
f.set_renderer('people', self.render_people_buefy)
|
||||||
f.set_renderer('people', self.render_people_buefy)
|
|
||||||
elif self.people_detachable and self.has_perm('detach_person'):
|
|
||||||
f.set_renderer('people', self.render_people_removable)
|
|
||||||
else:
|
|
||||||
f.set_renderer('people', self.render_people)
|
|
||||||
else:
|
else:
|
||||||
f.remove('people')
|
f.remove('people')
|
||||||
|
|
||||||
|
@ -288,30 +279,28 @@ class CustomerView(MasterView):
|
||||||
|
|
||||||
kwargs['show_profiles_helper'] = self.show_profiles_helper
|
kwargs['show_profiles_helper'] = self.show_profiles_helper
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
customer = kwargs['instance']
|
||||||
if use_buefy:
|
people = []
|
||||||
customer = kwargs['instance']
|
for person in customer.people:
|
||||||
people = []
|
data = {
|
||||||
for person in customer.people:
|
'uuid': person.uuid,
|
||||||
data = {
|
'full_name': person.display_name,
|
||||||
'uuid': person.uuid,
|
'first_name': person.first_name,
|
||||||
'full_name': person.display_name,
|
'last_name': person.last_name,
|
||||||
'first_name': person.first_name,
|
'_action_url_view': self.request.route_url('people.view',
|
||||||
'last_name': person.last_name,
|
uuid=person.uuid),
|
||||||
'_action_url_view': self.request.route_url('people.view',
|
}
|
||||||
uuid=person.uuid),
|
if self.editable and self.request.has_perm('people.edit'):
|
||||||
}
|
data['_action_url_edit'] = self.request.route_url(
|
||||||
if self.editable and self.request.has_perm('people.edit'):
|
'people.edit',
|
||||||
data['_action_url_edit'] = self.request.route_url(
|
uuid=person.uuid)
|
||||||
'people.edit',
|
if self.people_detachable and self.has_perm('detach_person'):
|
||||||
uuid=person.uuid)
|
data['_action_url_detach'] = self.request.route_url(
|
||||||
if self.people_detachable and self.has_perm('detach_person'):
|
'customers.detach_person',
|
||||||
data['_action_url_detach'] = self.request.route_url(
|
uuid=customer.uuid,
|
||||||
'customers.detach_person',
|
person_uuid=person.uuid)
|
||||||
uuid=customer.uuid,
|
people.append(data)
|
||||||
person_uuid=person.uuid)
|
kwargs['people_data'] = people
|
||||||
people.append(data)
|
|
||||||
kwargs['people_data'] = people
|
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
@ -326,20 +315,20 @@ class CustomerView(MasterView):
|
||||||
|
|
||||||
def render_default_address(self, customer, field):
|
def render_default_address(self, customer, field):
|
||||||
if customer.addresses:
|
if customer.addresses:
|
||||||
return six.text_type(customer.addresses[0])
|
return str(customer.addresses[0])
|
||||||
|
|
||||||
def grid_render_person(self, customer, field):
|
def grid_render_person(self, customer, field):
|
||||||
person = getattr(customer, field)
|
person = getattr(customer, field)
|
||||||
if not person:
|
if not person:
|
||||||
return ""
|
return ""
|
||||||
return six.text_type(person)
|
return str(person)
|
||||||
|
|
||||||
def form_render_person(self, customer, field):
|
def form_render_person(self, customer, field):
|
||||||
person = getattr(customer, field)
|
person = getattr(customer, field)
|
||||||
if not person:
|
if not person:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
url = self.request.route_url('people.view', uuid=person.uuid)
|
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -350,12 +339,13 @@ class CustomerView(MasterView):
|
||||||
|
|
||||||
items = []
|
items = []
|
||||||
for person in people:
|
for person in people:
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
url = self.request.route_url('people.view', uuid=person.uuid)
|
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||||
link = tags.link_to(text, url)
|
link = tags.link_to(text, url)
|
||||||
items.append(HTML.tag('li', c=[link]))
|
items.append(HTML.tag('li', c=[link]))
|
||||||
return HTML.tag('ul', c=items)
|
return HTML.tag('ul', c=items)
|
||||||
|
|
||||||
|
# TODO: remove if no longer used
|
||||||
def render_people_removable(self, customer, field):
|
def render_people_removable(self, customer, field):
|
||||||
people = customer.people
|
people = customer.people
|
||||||
if not people:
|
if not people:
|
||||||
|
@ -431,7 +421,7 @@ class CustomerView(MasterView):
|
||||||
return ""
|
return ""
|
||||||
items = []
|
items = []
|
||||||
for member in members:
|
for member in members:
|
||||||
text = six.text_type(member)
|
text = str(member)
|
||||||
url = self.request.route_url('members.view', uuid=member.uuid)
|
url = self.request.route_url('members.view', uuid=member.uuid)
|
||||||
items.append(HTML.tag('li', tags.link_to(text, url)))
|
items.append(HTML.tag('li', tags.link_to(text, url)))
|
||||||
return HTML.tag('ul', HTML.literal('').join(items))
|
return HTML.tag('ul', HTML.literal('').join(items))
|
||||||
|
@ -587,7 +577,7 @@ class PendingCustomerView(MasterView):
|
||||||
g.set_enum('status_code', self.enum.PENDING_CUSTOMER_STATUS)
|
g.set_enum('status_code', self.enum.PENDING_CUSTOMER_STATUS)
|
||||||
g.filters['status_code'].default_active = True
|
g.filters['status_code'].default_active = True
|
||||||
g.filters['status_code'].default_verb = 'not_equal'
|
g.filters['status_code'].default_verb = 'not_equal'
|
||||||
g.filters['status_code'].default_value = six.text_type(self.enum.PENDING_CUSTOMER_STATUS_RESOLVED)
|
g.filters['status_code'].default_value = str(self.enum.PENDING_CUSTOMER_STATUS_RESOLVED)
|
||||||
|
|
||||||
g.set_sort_defaults('display_name')
|
g.set_sort_defaults('display_name')
|
||||||
g.set_link('id')
|
g.set_link('id')
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,11 +24,8 @@
|
||||||
Customer order item views
|
Customer order item views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import six
|
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
@ -156,7 +153,7 @@ class CustomerOrderItemView(MasterView):
|
||||||
def render_person_text(self, item, field):
|
def render_person_text(self, item, field):
|
||||||
person = item.order.person
|
person = item.order.person
|
||||||
if person:
|
if person:
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def render_order_created(self, item, column):
|
def render_order_created(self, item, column):
|
||||||
|
@ -165,14 +162,13 @@ class CustomerOrderItemView(MasterView):
|
||||||
|
|
||||||
def render_status_code_column(self, item, field):
|
def render_status_code_column(self, item, field):
|
||||||
text = self.enum.CUSTORDER_ITEM_STATUS.get(item.status_code,
|
text = self.enum.CUSTORDER_ITEM_STATUS.get(item.status_code,
|
||||||
six.text_type(item.status_code))
|
str(item.status_code))
|
||||||
if item.status_text:
|
if item.status_text:
|
||||||
return HTML.tag('span', title=item.status_text, c=[text])
|
return HTML.tag('span', title=item.status_text, c=[text])
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(CustomerOrderItemView, self).configure_form(f)
|
super(CustomerOrderItemView, self).configure_form(f)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
item = f.model_instance
|
item = f.model_instance
|
||||||
|
|
||||||
# order
|
# order
|
||||||
|
@ -222,10 +218,7 @@ class CustomerOrderItemView(MasterView):
|
||||||
f.set_renderer('status_code', self.render_status_code)
|
f.set_renderer('status_code', self.render_status_code)
|
||||||
|
|
||||||
# notes
|
# notes
|
||||||
if use_buefy:
|
f.set_renderer('notes', self.render_notes)
|
||||||
f.set_renderer('notes', self.render_notes)
|
|
||||||
else:
|
|
||||||
f.remove('notes')
|
|
||||||
|
|
||||||
def highlight_pending_field(self, item, field, value=None):
|
def highlight_pending_field(self, item, field, value=None):
|
||||||
if value is None:
|
if value is None:
|
||||||
|
@ -271,13 +264,12 @@ class CustomerOrderItemView(MasterView):
|
||||||
return outer
|
return outer
|
||||||
|
|
||||||
def render_status_code(self, item, field):
|
def render_status_code(self, item, field):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
text = self.enum.CUSTORDER_ITEM_STATUS[item.status_code]
|
text = self.enum.CUSTORDER_ITEM_STATUS[item.status_code]
|
||||||
if item.status_text:
|
if item.status_text:
|
||||||
text = "{} ({})".format(text, item.status_text)
|
text = "{} ({})".format(text, item.status_text)
|
||||||
items = [HTML.tag('span', c=[text])]
|
items = [HTML.tag('span', c=[text])]
|
||||||
|
|
||||||
if use_buefy and self.has_perm('change_status'):
|
if self.has_perm('change_status'):
|
||||||
button = HTML.tag('b-button', type='is-primary', c="Change Status",
|
button = HTML.tag('b-button', type='is-primary', c="Change Status",
|
||||||
style='margin-left: 1rem;',
|
style='margin-left: 1rem;',
|
||||||
icon_pack='fas', icon_left='edit',
|
icon_pack='fas', icon_left='edit',
|
||||||
|
@ -484,14 +476,14 @@ class CustomerOrderItemView(MasterView):
|
||||||
order = item.order
|
order = item.order
|
||||||
if not order:
|
if not order:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(order)
|
text = str(order)
|
||||||
url = self.request.route_url('custorders.view', uuid=order.uuid)
|
url = self.request.route_url('custorders.view', uuid=order.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
def render_person(self, item, field):
|
def render_person(self, item, field):
|
||||||
person = item.order.person
|
person = item.order.person
|
||||||
if person:
|
if person:
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
url = self.request.route_url('people.view', uuid=person.uuid)
|
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
|
|
@ -24,15 +24,10 @@
|
||||||
Department Views
|
Department Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
from webhelpers2.html import HTML
|
from webhelpers2.html import HTML
|
||||||
|
|
||||||
from tailbone import grids
|
|
||||||
from tailbone.views import MasterView
|
from tailbone.views import MasterView
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,11 +94,10 @@ class DepartmentView(MasterView):
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(DepartmentView, self).configure_form(f)
|
super(DepartmentView, self).configure_form(f)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
f.remove_field('subdepartments')
|
f.remove_field('subdepartments')
|
||||||
|
|
||||||
if not use_buefy or self.creating or self.editing:
|
if self.creating or self.editing:
|
||||||
f.remove('employees')
|
f.remove('employees')
|
||||||
else:
|
else:
|
||||||
f.set_renderer('employees', self.render_employees)
|
f.set_renderer('employees', self.render_employees)
|
||||||
|
@ -137,33 +131,20 @@ class DepartmentView(MasterView):
|
||||||
|
|
||||||
def template_kwargs_view(self, **kwargs):
|
def template_kwargs_view(self, **kwargs):
|
||||||
kwargs = super(DepartmentView, self).template_kwargs_view(**kwargs)
|
kwargs = super(DepartmentView, self).template_kwargs_view(**kwargs)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
department = kwargs['instance']
|
department = kwargs['instance']
|
||||||
department_employees = sorted(department.employees, key=six.text_type)
|
department_employees = sorted(department.employees, key=str)
|
||||||
|
|
||||||
if use_buefy:
|
employees = []
|
||||||
employees = []
|
for employee in department_employees:
|
||||||
for employee in department_employees:
|
person = employee.person
|
||||||
person = employee.person
|
employees.append({
|
||||||
employees.append({
|
'uuid': employee.uuid,
|
||||||
'uuid': employee.uuid,
|
'first_name': person.first_name,
|
||||||
'first_name': person.first_name,
|
'last_name': person.last_name,
|
||||||
'last_name': person.last_name,
|
'_action_url_view': self.request.route_url('employees.view', uuid=employee.uuid),
|
||||||
'_action_url_view': self.request.route_url('employees.view', uuid=employee.uuid),
|
'_action_url_edit': self.request.route_url('employees.edit', uuid=employee.uuid),
|
||||||
'_action_url_edit': self.request.route_url('employees.edit', uuid=employee.uuid),
|
})
|
||||||
})
|
kwargs['employees_data'] = employees
|
||||||
kwargs['employees_data'] = employees
|
|
||||||
|
|
||||||
else: # not buefy
|
|
||||||
if department.employees:
|
|
||||||
actions = [
|
|
||||||
grids.GridAction('view', icon='zoomin',
|
|
||||||
url=lambda r, i: self.request.route_url('employees.view', uuid=r.uuid))
|
|
||||||
]
|
|
||||||
kwargs['employees'] = grids.Grid(None, department_employees, ['display_name'], request=self.request,
|
|
||||||
model_class=model.Employee, main_actions=actions)
|
|
||||||
else:
|
|
||||||
kwargs['employees'] = None
|
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
@ -218,33 +199,14 @@ class DepartmentView(MasterView):
|
||||||
.distinct()\
|
.distinct()\
|
||||||
.order_by(model.Department.name)
|
.order_by(model.Department.name)
|
||||||
|
|
||||||
if self.get_use_buefy():
|
def normalize(dept):
|
||||||
|
return {
|
||||||
|
'uuid': dept.uuid,
|
||||||
|
'number': dept.number,
|
||||||
|
'name': dept.name,
|
||||||
|
}
|
||||||
|
|
||||||
def normalize(dept):
|
return self.json_response([normalize(d) for d in data])
|
||||||
return {
|
|
||||||
'uuid': dept.uuid,
|
|
||||||
'number': dept.number,
|
|
||||||
'name': dept.name,
|
|
||||||
}
|
|
||||||
|
|
||||||
return self.json_response([normalize(d) for d in data])
|
|
||||||
|
|
||||||
# nb. the rest of this is legacy / not buefy
|
|
||||||
|
|
||||||
def configure(g):
|
|
||||||
g.configure(include=[
|
|
||||||
g.name,
|
|
||||||
], readonly=True)
|
|
||||||
|
|
||||||
def row_attrs(row, i):
|
|
||||||
return {'data-uuid': row.uuid}
|
|
||||||
|
|
||||||
grid = self.make_grid(data=data, sortable=False, filterable=False, pageable=False,
|
|
||||||
configure=configure, width=None, checkboxes=True,
|
|
||||||
row_attrs=row_attrs, main_actions=[], more_actions=[])
|
|
||||||
self.request.response.content_type = str('text/html')
|
|
||||||
self.request.response.text = grid.render_grid()
|
|
||||||
return self.request.response
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def defaults(cls, config):
|
def defaults(cls, config):
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,9 +24,6 @@
|
||||||
Employee Views
|
Employee Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import six
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
@ -84,7 +81,6 @@ class EmployeeView(MasterView):
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super(EmployeeView, self).configure_grid(g)
|
super(EmployeeView, self).configure_grid(g)
|
||||||
route_prefix = self.get_route_prefix()
|
route_prefix = self.get_route_prefix()
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# phone
|
# phone
|
||||||
g.set_joiner('phone', lambda q: q.outerjoin(model.EmployeePhoneNumber, sa.and_(
|
g.set_joiner('phone', lambda q: q.outerjoin(model.EmployeePhoneNumber, sa.and_(
|
||||||
|
@ -127,10 +123,7 @@ class EmployeeView(MasterView):
|
||||||
g.set_enum('status', self.enum.EMPLOYEE_STATUS)
|
g.set_enum('status', self.enum.EMPLOYEE_STATUS)
|
||||||
g.filters['status'].default_active = True
|
g.filters['status'].default_active = True
|
||||||
g.filters['status'].default_verb = 'equal'
|
g.filters['status'].default_verb = 'equal'
|
||||||
if use_buefy:
|
g.filters['status'].default_value = str(self.enum.EMPLOYEE_STATUS_CURRENT)
|
||||||
g.filters['status'].default_value = six.text_type(self.enum.EMPLOYEE_STATUS_CURRENT)
|
|
||||||
else:
|
|
||||||
g.filters['status'].default_value = self.enum.EMPLOYEE_STATUS_CURRENT
|
|
||||||
else:
|
else:
|
||||||
g.remove('status')
|
g.remove('status')
|
||||||
del g.filters['status']
|
del g.filters['status']
|
||||||
|
@ -202,7 +195,7 @@ class EmployeeView(MasterView):
|
||||||
f.set_label('stores', "Stores") # TODO: should not be necessary
|
f.set_label('stores', "Stores") # TODO: should not be necessary
|
||||||
if self.creating or self.editing:
|
if self.creating or self.editing:
|
||||||
stores = self.get_possible_stores().all()
|
stores = self.get_possible_stores().all()
|
||||||
store_values = [(s.uuid, six.text_type(s)) for s in stores]
|
store_values = [(s.uuid, str(s)) for s in stores]
|
||||||
f.set_node('stores', colander.SchemaNode(colander.Set()))
|
f.set_node('stores', colander.SchemaNode(colander.Set()))
|
||||||
f.set_widget('stores', dfwidget.SelectWidget(multiple=True,
|
f.set_widget('stores', dfwidget.SelectWidget(multiple=True,
|
||||||
size=len(stores),
|
size=len(stores),
|
||||||
|
@ -214,7 +207,7 @@ class EmployeeView(MasterView):
|
||||||
f.set_label('departments', "Departments") # TODO: should not be necessary
|
f.set_label('departments', "Departments") # TODO: should not be necessary
|
||||||
if self.creating or self.editing:
|
if self.creating or self.editing:
|
||||||
departments = self.get_possible_departments().all()
|
departments = self.get_possible_departments().all()
|
||||||
dept_values = [(d.uuid, six.text_type(d)) for d in departments]
|
dept_values = [(d.uuid, str(d)) for d in departments]
|
||||||
f.set_node('departments', colander.SchemaNode(colander.Set()))
|
f.set_node('departments', colander.SchemaNode(colander.Set()))
|
||||||
f.set_widget('departments', dfwidget.SelectWidget(multiple=True,
|
f.set_widget('departments', dfwidget.SelectWidget(multiple=True,
|
||||||
size=len(departments),
|
size=len(departments),
|
||||||
|
@ -284,7 +277,7 @@ class EmployeeView(MasterView):
|
||||||
person = employee.person if employee else None
|
person = employee.person if employee else None
|
||||||
if not person:
|
if not person:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
url = self.request.route_url('people.view', uuid=person.uuid)
|
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -293,8 +286,8 @@ class EmployeeView(MasterView):
|
||||||
if not stores:
|
if not stores:
|
||||||
return ""
|
return ""
|
||||||
items = []
|
items = []
|
||||||
for store in sorted(stores, key=six.text_type):
|
for store in sorted(stores, key=str):
|
||||||
items.append(HTML.tag('li', c=six.text_type(store)))
|
items.append(HTML.tag('li', c=str(store)))
|
||||||
return HTML.tag('ul', c=items)
|
return HTML.tag('ul', c=items)
|
||||||
|
|
||||||
def render_departments(self, employee, field):
|
def render_departments(self, employee, field):
|
||||||
|
@ -302,8 +295,8 @@ class EmployeeView(MasterView):
|
||||||
if not departments:
|
if not departments:
|
||||||
return ""
|
return ""
|
||||||
items = []
|
items = []
|
||||||
for department in sorted(departments, key=six.text_type):
|
for department in sorted(departments, key=str):
|
||||||
items.append(HTML.tag('li', c=six.text_type(department)))
|
items.append(HTML.tag('li', c=str(department)))
|
||||||
return HTML.tag('ul', c=items)
|
return HTML.tag('ul', c=items)
|
||||||
|
|
||||||
def touch_instance(self, employee):
|
def touch_instance(self, employee):
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,9 +24,6 @@
|
||||||
Feature views
|
Feature views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import six
|
|
||||||
import colander
|
import colander
|
||||||
import markdown
|
import markdown
|
||||||
|
|
||||||
|
@ -49,20 +46,16 @@ class GenerateFeatureView(View):
|
||||||
return handler
|
return handler
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
schema = self.handler.make_schema()
|
schema = self.handler.make_schema()
|
||||||
app_form = forms.Form(schema=schema, request=self.request,
|
app_form = forms.Form(schema=schema, request=self.request)
|
||||||
use_buefy=use_buefy)
|
for key, value in self.handler.get_defaults().items():
|
||||||
for key, value in six.iteritems(self.handler.get_defaults()):
|
|
||||||
app_form.set_default(key, value)
|
app_form.set_default(key, value)
|
||||||
|
|
||||||
feature_forms = {}
|
feature_forms = {}
|
||||||
for feature in self.handler.iter_features():
|
for feature in self.handler.iter_features():
|
||||||
schema = feature.make_schema()
|
schema = feature.make_schema()
|
||||||
form = forms.Form(schema=schema, request=self.request,
|
form = forms.Form(schema=schema, request=self.request)
|
||||||
use_buefy=use_buefy)
|
for key, value in feature.get_defaults().items():
|
||||||
for key, value in six.iteritems(feature.get_defaults()):
|
|
||||||
form.set_default(key, value)
|
form.set_default(key, value)
|
||||||
feature_forms[feature.feature_key] = form
|
feature_forms[feature.feature_key] = form
|
||||||
|
|
||||||
|
@ -86,7 +79,6 @@ class GenerateFeatureView(View):
|
||||||
context = {
|
context = {
|
||||||
'index_title': "Generate Feature",
|
'index_title': "Generate Feature",
|
||||||
'handler': self.handler,
|
'handler': self.handler,
|
||||||
'use_buefy': use_buefy,
|
|
||||||
'app_form': app_form,
|
'app_form': app_form,
|
||||||
'feature_type': feature_type,
|
'feature_type': feature_type,
|
||||||
'feature_forms': feature_forms,
|
'feature_forms': feature_forms,
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
View for running arbitrary import/export jobs
|
View for running arbitrary import/export jobs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import getpass
|
import getpass
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
@ -34,7 +32,6 @@ import subprocess
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import six
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from rattail.exceptions import ConfigurationError
|
from rattail.exceptions import ConfigurationError
|
||||||
|
@ -222,7 +219,7 @@ class ImportingView(MasterView):
|
||||||
try:
|
try:
|
||||||
return self.do_runjob(handler_info, form)
|
return self.do_runjob(handler_info, form)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
self.request.session.flash(six.text_type(error), 'error')
|
self.request.session.flash(str(error), 'error')
|
||||||
return self.redirect(self.request.current_route_url())
|
return self.redirect(self.request.current_route_url())
|
||||||
|
|
||||||
return self.render_to_response('runjob', {
|
return self.render_to_response('runjob', {
|
||||||
|
@ -274,7 +271,6 @@ class ImportingView(MasterView):
|
||||||
handler = handler_info['_handler']
|
handler = handler_info['_handler']
|
||||||
defaults = {
|
defaults = {
|
||||||
'request': self.request,
|
'request': self.request,
|
||||||
'use_buefy': self.get_use_buefy(),
|
|
||||||
'model_instance': handler,
|
'model_instance': handler,
|
||||||
'cancel_url': self.request.route_url('{}.view'.format(route_prefix),
|
'cancel_url': self.request.route_url('{}.view'.format(route_prefix),
|
||||||
key=handler.get_key()),
|
key=handler.get_key()),
|
||||||
|
@ -411,8 +407,7 @@ And here is the output:
|
||||||
data = json.dumps({
|
data = json.dumps({
|
||||||
'everything_complete': True,
|
'everything_complete': True,
|
||||||
})
|
})
|
||||||
if six.PY3:
|
data = data.encode('utf_8')
|
||||||
data = data.encode('utf_8')
|
|
||||||
cxn.send(data)
|
cxn.send(data)
|
||||||
cxn.send(suffix)
|
cxn.send(suffix)
|
||||||
cxn.close()
|
cxn.close()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,8 +24,6 @@
|
||||||
Label Profile Views
|
Label Profile Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
|
@ -93,7 +91,6 @@ class LabelProfileView(MasterView):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def make_printer_settings_form(self, profile, printer):
|
def make_printer_settings_form(self, profile, printer):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
schema = colander.Schema()
|
schema = colander.Schema()
|
||||||
|
|
||||||
for name, label in printer.required_settings.items():
|
for name, label in printer.required_settings.items():
|
||||||
|
@ -104,7 +101,6 @@ class LabelProfileView(MasterView):
|
||||||
schema.add(node)
|
schema.add(node)
|
||||||
|
|
||||||
form = forms.Form(schema=schema, request=self.request,
|
form = forms.Form(schema=schema, request=self.request,
|
||||||
use_buefy=use_buefy,
|
|
||||||
model_instance=profile,
|
model_instance=profile,
|
||||||
# TODO: ugh, this is necessary to avoid some logic
|
# TODO: ugh, this is necessary to avoid some logic
|
||||||
# which assumes a ColanderAlchemy schema i think?
|
# which assumes a ColanderAlchemy schema i think?
|
||||||
|
|
|
@ -24,15 +24,12 @@
|
||||||
Views for Luigi
|
Views for Luigi
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
|
||||||
import six
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from rattail.util import simple_error
|
from rattail.util import simple_error
|
||||||
|
@ -81,7 +78,6 @@ class LuigiTaskView(MasterView):
|
||||||
luigi_url = self.rattail_config.get('rattail.luigi', 'url')
|
luigi_url = self.rattail_config.get('rattail.luigi', 'url')
|
||||||
history_url = '{}/history'.format(luigi_url.rstrip('/')) if luigi_url else None
|
history_url = '{}/history'.format(luigi_url.rstrip('/')) if luigi_url else None
|
||||||
return self.render_to_response('index', {
|
return self.render_to_response('index', {
|
||||||
'use_buefy': self.get_use_buefy(),
|
|
||||||
'index_url': None,
|
'index_url': None,
|
||||||
'luigi_url': luigi_url,
|
'luigi_url': luigi_url,
|
||||||
'luigi_history_url': history_url,
|
'luigi_history_url': history_url,
|
||||||
|
@ -169,7 +165,7 @@ class LuigiTaskView(MasterView):
|
||||||
tasks = []
|
tasks = []
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
if task['last_date']:
|
if task['last_date']:
|
||||||
task['last_date'] = six.text_type(task['last_date'])
|
task['last_date'] = str(task['last_date'])
|
||||||
return tasks
|
return tasks
|
||||||
|
|
||||||
def get_backfill_tasks(self):
|
def get_backfill_tasks(self):
|
||||||
|
@ -179,9 +175,9 @@ class LuigiTaskView(MasterView):
|
||||||
tasks = []
|
tasks = []
|
||||||
for task in tasks:
|
for task in tasks:
|
||||||
if task['last_date']:
|
if task['last_date']:
|
||||||
task['last_date'] = six.text_type(task['last_date'])
|
task['last_date'] = str(task['last_date'])
|
||||||
if task['target_date']:
|
if task['target_date']:
|
||||||
task['target_date'] = six.text_type(task['target_date'])
|
task['target_date'] = str(task['target_date'])
|
||||||
return tasks
|
return tasks
|
||||||
|
|
||||||
def configure_gather_settings(self, data):
|
def configure_gather_settings(self, data):
|
||||||
|
@ -224,7 +220,7 @@ class LuigiTaskView(MasterView):
|
||||||
{'name': 'rattail.luigi.backfill.task.{}.notes'.format(key),
|
{'name': 'rattail.luigi.backfill.task.{}.notes'.format(key),
|
||||||
'value': task['notes']},
|
'value': task['notes']},
|
||||||
{'name': 'rattail.luigi.backfill.task.{}.target_date'.format(key),
|
{'name': 'rattail.luigi.backfill.task.{}.target_date'.format(key),
|
||||||
'value': six.text_type(task['target_date'])},
|
'value': str(task['target_date'])},
|
||||||
])
|
])
|
||||||
if keys:
|
if keys:
|
||||||
settings.append({'name': 'rattail.luigi.backfill.tasks',
|
settings.append({'name': 'rattail.luigi.backfill.tasks',
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
Model Master View
|
Model Master View
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import csv
|
import csv
|
||||||
import datetime
|
import datetime
|
||||||
|
@ -252,7 +250,7 @@ class MasterView(View):
|
||||||
|
|
||||||
def set_labels(self, obj):
|
def set_labels(self, obj):
|
||||||
labels = self.collect_labels()
|
labels = self.collect_labels()
|
||||||
for key, label in six.iteritems(labels):
|
for key, label in labels.items():
|
||||||
obj.set_label(key, label)
|
obj.set_label(key, label)
|
||||||
|
|
||||||
def collect_labels(self):
|
def collect_labels(self):
|
||||||
|
@ -283,7 +281,7 @@ class MasterView(View):
|
||||||
|
|
||||||
def set_row_labels(self, obj):
|
def set_row_labels(self, obj):
|
||||||
labels = self.collect_row_labels()
|
labels = self.collect_row_labels()
|
||||||
for key, label in six.iteritems(labels):
|
for key, label in labels.items():
|
||||||
obj.set_label(key, label)
|
obj.set_label(key, label)
|
||||||
|
|
||||||
def collect_row_labels(self):
|
def collect_row_labels(self):
|
||||||
|
@ -333,7 +331,6 @@ class MasterView(View):
|
||||||
"""
|
"""
|
||||||
self.listing = True
|
self.listing = True
|
||||||
grid = self.make_grid()
|
grid = self.make_grid()
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# If user just refreshed the page with a reset instruction, issue a
|
# If user just refreshed the page with a reset instruction, issue a
|
||||||
# redirect in order to clear out the query string.
|
# redirect in order to clear out the query string.
|
||||||
|
@ -346,14 +343,9 @@ class MasterView(View):
|
||||||
|
|
||||||
# return grid only, if partial page was requested
|
# return grid only, if partial page was requested
|
||||||
if self.request.params.get('partial'):
|
if self.request.params.get('partial'):
|
||||||
if use_buefy:
|
# render grid data only, as JSON
|
||||||
# render grid data only, as JSON
|
return render_to_response('json', grid.get_buefy_data(),
|
||||||
return render_to_response('json', grid.get_buefy_data(),
|
request=self.request)
|
||||||
request=self.request)
|
|
||||||
else: # just do traditional thing, render grid HTML
|
|
||||||
self.request.response.content_type = str('text/html')
|
|
||||||
self.request.response.text = grid.render_grid()
|
|
||||||
return self.request.response
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'grid': grid,
|
'grid': grid,
|
||||||
|
@ -552,17 +544,16 @@ class MasterView(View):
|
||||||
|
|
||||||
if self.has_rows and 'main_actions' not in defaults:
|
if self.has_rows and 'main_actions' not in defaults:
|
||||||
actions = []
|
actions = []
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# view action
|
# view action
|
||||||
if self.rows_viewable:
|
if self.rows_viewable:
|
||||||
icon = 'eye' if use_buefy else 'zoomin'
|
actions.append(self.make_action('view', icon='eye',
|
||||||
actions.append(self.make_action('view', icon=icon, url=self.row_view_action_url))
|
url=self.row_view_action_url))
|
||||||
|
|
||||||
# edit action
|
# edit action
|
||||||
if self.rows_editable and self.has_perm('edit_row'):
|
if self.rows_editable and self.has_perm('edit_row'):
|
||||||
icon = 'edit' if use_buefy else 'pencil'
|
actions.append(self.make_action('edit', icon='edit',
|
||||||
actions.append(self.make_action('edit', icon=icon, url=self.row_edit_action_url))
|
url=self.row_edit_action_url))
|
||||||
|
|
||||||
# delete action
|
# delete action
|
||||||
if self.rows_deletable and self.has_perm('delete_row'):
|
if self.rows_deletable and self.has_perm('delete_row'):
|
||||||
|
@ -626,7 +617,6 @@ class MasterView(View):
|
||||||
Return a dictionary of kwargs to be passed to the factory when
|
Return a dictionary of kwargs to be passed to the factory when
|
||||||
constructing a new version grid.
|
constructing a new version grid.
|
||||||
"""
|
"""
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
instance = kwargs.get('instance') or self.get_instance()
|
instance = kwargs.get('instance') or self.get_instance()
|
||||||
route = '{}.version'.format(self.get_route_prefix())
|
route = '{}.version'.format(self.get_route_prefix())
|
||||||
defaults = {
|
defaults = {
|
||||||
|
@ -638,7 +628,7 @@ class MasterView(View):
|
||||||
if 'main_actions' not in kwargs:
|
if 'main_actions' not in kwargs:
|
||||||
url = lambda txn, i: self.request.route_url(route, uuid=instance.uuid, txnid=txn.id)
|
url = lambda txn, i: self.request.route_url(route, uuid=instance.uuid, txnid=txn.id)
|
||||||
defaults['main_actions'] = [
|
defaults['main_actions'] = [
|
||||||
self.make_action('view', icon='eye' if use_buefy else 'zoomin', url=url),
|
self.make_action('view', icon='eye', url=url),
|
||||||
]
|
]
|
||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
return defaults
|
return defaults
|
||||||
|
@ -735,11 +725,10 @@ class MasterView(View):
|
||||||
delete=False, schema=None, importer_host_title=None):
|
delete=False, schema=None, importer_host_title=None):
|
||||||
|
|
||||||
handler = handler_factory(self.rattail_config)
|
handler = handler_factory(self.rattail_config)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
if not schema:
|
if not schema:
|
||||||
schema = forms.SimpleFileImport().bind(request=self.request)
|
schema = forms.SimpleFileImport().bind(request=self.request)
|
||||||
form = forms.Form(schema=schema, request=self.request, use_buefy=use_buefy)
|
form = forms.Form(schema=schema, request=self.request)
|
||||||
form.save_label = "Upload"
|
form.save_label = "Upload"
|
||||||
form.cancel_url = self.get_index_url()
|
form.cancel_url = self.get_index_url()
|
||||||
if form.validate(newstyle=True):
|
if form.validate(newstyle=True):
|
||||||
|
@ -771,7 +760,7 @@ class MasterView(View):
|
||||||
value = getattr(obj, field)
|
value = getattr(obj, field)
|
||||||
if value is None:
|
if value is None:
|
||||||
return ""
|
return ""
|
||||||
value = six.text_type(value)
|
value = str(value)
|
||||||
if len(value) > 100:
|
if len(value) > 100:
|
||||||
value = value[:100] + '...'
|
value = value[:100] + '...'
|
||||||
return value
|
return value
|
||||||
|
@ -841,7 +830,7 @@ class MasterView(View):
|
||||||
product = getattr(obj, field)
|
product = getattr(obj, field)
|
||||||
if not product:
|
if not product:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(product)
|
text = str(product)
|
||||||
url = self.request.route_url('products.view', uuid=product.uuid)
|
url = self.request.route_url('products.view', uuid=product.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -849,7 +838,7 @@ class MasterView(View):
|
||||||
pending = getattr(obj, field)
|
pending = getattr(obj, field)
|
||||||
if not pending:
|
if not pending:
|
||||||
return
|
return
|
||||||
text = six.text_type(pending)
|
text = str(pending)
|
||||||
url = self.request.route_url('pending_products.view', uuid=pending.uuid)
|
url = self.request.route_url('pending_products.view', uuid=pending.uuid)
|
||||||
return tags.link_to(text, url,
|
return tags.link_to(text, url,
|
||||||
class_='has-background-warning')
|
class_='has-background-warning')
|
||||||
|
@ -862,7 +851,7 @@ class MasterView(View):
|
||||||
if short:
|
if short:
|
||||||
text = "({}) {}".format(short, vendor.name)
|
text = "({}) {}".format(short, vendor.name)
|
||||||
else:
|
else:
|
||||||
text = six.text_type(vendor)
|
text = str(vendor)
|
||||||
url = self.request.route_url('vendors.view', uuid=vendor.uuid)
|
url = self.request.route_url('vendors.view', uuid=vendor.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -918,7 +907,7 @@ class MasterView(View):
|
||||||
person = getattr(obj, field)
|
person = getattr(obj, field)
|
||||||
if not person:
|
if not person:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
url = self.request.route_url('people.view', uuid=person.uuid)
|
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -926,7 +915,7 @@ class MasterView(View):
|
||||||
person = getattr(obj, field)
|
person = getattr(obj, field)
|
||||||
if not person:
|
if not person:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
url = self.request.route_url('people.view_profile', uuid=person.uuid)
|
url = self.request.route_url('people.view_profile', uuid=person.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -934,7 +923,7 @@ class MasterView(View):
|
||||||
user = getattr(obj, field)
|
user = getattr(obj, field)
|
||||||
if not user:
|
if not user:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(user)
|
text = str(user)
|
||||||
url = self.request.route_url('users.view', uuid=user.uuid)
|
url = self.request.route_url('users.view', uuid=user.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -954,7 +943,7 @@ class MasterView(View):
|
||||||
customer = getattr(obj, field)
|
customer = getattr(obj, field)
|
||||||
if not customer:
|
if not customer:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(customer)
|
text = str(customer)
|
||||||
url = self.request.route_url('customers.view', uuid=customer.uuid)
|
url = self.request.route_url('customers.view', uuid=customer.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -984,7 +973,7 @@ class MasterView(View):
|
||||||
value = obj.status_code
|
value = obj.status_code
|
||||||
if value is None:
|
if value is None:
|
||||||
return ""
|
return ""
|
||||||
status_code_text = enum.get(value, six.text_type(value))
|
status_code_text = enum.get(value, str(value))
|
||||||
if obj.status_text:
|
if obj.status_text:
|
||||||
return HTML.tag('span', title=obj.status_text, c=status_code_text)
|
return HTML.tag('span', title=obj.status_text, c=status_code_text)
|
||||||
return status_code_text
|
return status_code_text
|
||||||
|
@ -1072,7 +1061,6 @@ class MasterView(View):
|
||||||
View for viewing details of an existing model record.
|
View for viewing details of an existing model record.
|
||||||
"""
|
"""
|
||||||
self.viewing = True
|
self.viewing = True
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
if instance is None:
|
if instance is None:
|
||||||
instance = self.get_instance()
|
instance = self.get_instance()
|
||||||
form = self.make_form(instance)
|
form = self.make_form(instance)
|
||||||
|
@ -1090,14 +1078,9 @@ class MasterView(View):
|
||||||
|
|
||||||
# return grid only, if partial page was requested
|
# return grid only, if partial page was requested
|
||||||
if self.request.params.get('partial'):
|
if self.request.params.get('partial'):
|
||||||
if use_buefy:
|
# render grid data only, as JSON
|
||||||
# render grid data only, as JSON
|
return render_to_response('json', grid.get_buefy_data(),
|
||||||
return render_to_response('json', grid.get_buefy_data(),
|
request=self.request)
|
||||||
request=self.request)
|
|
||||||
else: # just do traditional thing, render grid HTML
|
|
||||||
self.request.response.content_type = str('text/html')
|
|
||||||
self.request.response.text = grid.render_grid()
|
|
||||||
return self.request.response
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'instance': instance,
|
'instance': instance,
|
||||||
|
@ -1112,12 +1095,8 @@ class MasterView(View):
|
||||||
context['dform'] = form.make_deform_form()
|
context['dform'] = form.make_deform_form()
|
||||||
|
|
||||||
if self.has_rows:
|
if self.has_rows:
|
||||||
if use_buefy:
|
context['rows_grid'] = grid
|
||||||
context['rows_grid'] = grid
|
context['rows_grid_tools'] = HTML(self.make_row_grid_tools(instance) or '').strip()
|
||||||
context['rows_grid_tools'] = HTML(self.make_row_grid_tools(instance) or '').strip()
|
|
||||||
else:
|
|
||||||
context['rows_grid'] = grid.render_complete(allow_save_defaults=False,
|
|
||||||
tools=self.make_row_grid_tools(instance))
|
|
||||||
|
|
||||||
return self.render_to_response('view', context)
|
return self.render_to_response('view', context)
|
||||||
|
|
||||||
|
@ -1224,18 +1203,12 @@ class MasterView(View):
|
||||||
instance = self.get_instance()
|
instance = self.get_instance()
|
||||||
instance_title = self.get_instance_title(instance)
|
instance_title = self.get_instance_title(instance)
|
||||||
grid = self.make_version_grid(instance=instance)
|
grid = self.make_version_grid(instance=instance)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# return grid only, if partial page was requested
|
# return grid only, if partial page was requested
|
||||||
if self.request.params.get('partial'):
|
if self.request.params.get('partial'):
|
||||||
if use_buefy:
|
# render grid data only, as JSON
|
||||||
# render grid data only, as JSON
|
return render_to_response('json', grid.get_buefy_data(),
|
||||||
return render_to_response('json', grid.get_buefy_data(),
|
request=self.request)
|
||||||
request=self.request)
|
|
||||||
else: # just do traditional thing, render grid HTML
|
|
||||||
self.request.response.content_type = str('text/html')
|
|
||||||
self.request.response.text = grid.render_grid()
|
|
||||||
return self.request.response
|
|
||||||
|
|
||||||
return self.render_to_response('versions', {
|
return self.render_to_response('versions', {
|
||||||
'instance': instance,
|
'instance': instance,
|
||||||
|
@ -1567,15 +1540,10 @@ class MasterView(View):
|
||||||
response.content_length = os.path.getsize(path)
|
response.content_length = os.path.getsize(path)
|
||||||
content_type = self.download_content_type(path, filename)
|
content_type = self.download_content_type(path, filename)
|
||||||
if content_type:
|
if content_type:
|
||||||
if six.PY3:
|
response.content_type = content_type
|
||||||
response.content_type = content_type
|
|
||||||
else:
|
|
||||||
response.content_type = six.binary_type(content_type)
|
|
||||||
|
|
||||||
# content-disposition
|
# content-disposition
|
||||||
filename = os.path.basename(path)
|
filename = os.path.basename(path)
|
||||||
if six.PY2:
|
|
||||||
filename = filename.encode('ascii', 'replace')
|
|
||||||
response.content_disposition = str('attachment; filename="{}"'.format(filename))
|
response.content_disposition = str('attachment; filename="{}"'.format(filename))
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
@ -1986,8 +1954,7 @@ class MasterView(View):
|
||||||
|
|
||||||
# strip suffix, interpret data as JSON
|
# strip suffix, interpret data as JSON
|
||||||
data = data[:-len(suffix)]
|
data = data[:-len(suffix)]
|
||||||
if six.PY3:
|
data = data.decode('utf_8')
|
||||||
data = data.decode('utf_8')
|
|
||||||
data = json.loads(data)
|
data = json.loads(data)
|
||||||
|
|
||||||
if data.get('everything_complete'):
|
if data.get('everything_complete'):
|
||||||
|
@ -2056,7 +2023,7 @@ class MasterView(View):
|
||||||
object_to_keep = self.Session.query(self.get_model_class()).get(uuids[1])
|
object_to_keep = self.Session.query(self.get_model_class()).get(uuids[1])
|
||||||
|
|
||||||
if object_to_remove and object_to_keep and self.request.POST.get('commit-merge') == 'yes':
|
if object_to_remove and object_to_keep and self.request.POST.get('commit-merge') == 'yes':
|
||||||
msg = six.text_type(object_to_remove)
|
msg = str(object_to_remove)
|
||||||
try:
|
try:
|
||||||
self.validate_merge(object_to_remove, object_to_keep)
|
self.validate_merge(object_to_remove, object_to_keep)
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
@ -2166,7 +2133,7 @@ class MasterView(View):
|
||||||
"""
|
"""
|
||||||
if hasattr(cls, 'model_key'):
|
if hasattr(cls, 'model_key'):
|
||||||
keys = cls.model_key
|
keys = cls.model_key
|
||||||
if isinstance(keys, six.string_types):
|
if isinstance(keys, str):
|
||||||
keys = [keys]
|
keys = [keys]
|
||||||
else:
|
else:
|
||||||
keys = get_primary_keys(cls.get_model_class())
|
keys = get_primary_keys(cls.get_model_class())
|
||||||
|
@ -2399,7 +2366,6 @@ class MasterView(View):
|
||||||
"""
|
"""
|
||||||
context = {
|
context = {
|
||||||
'master': self,
|
'master': self,
|
||||||
'use_buefy': self.get_use_buefy(),
|
|
||||||
'model_title': self.get_model_title(),
|
'model_title': self.get_model_title(),
|
||||||
'model_title_plural': self.get_model_title_plural(),
|
'model_title_plural': self.get_model_title_plural(),
|
||||||
'route_prefix': self.get_route_prefix(),
|
'route_prefix': self.get_route_prefix(),
|
||||||
|
@ -2699,7 +2665,7 @@ class MasterView(View):
|
||||||
# nb. unfortunately HTML.tag() calls its first arg 'tag' and
|
# nb. unfortunately HTML.tag() calls its first arg 'tag' and
|
||||||
# so we can't pass a kwarg with that name...so instead we
|
# so we can't pass a kwarg with that name...so instead we
|
||||||
# patch that into place manually
|
# patch that into place manually
|
||||||
button = six.text_type(button)
|
button = str(button)
|
||||||
button = button.replace('<b-button ',
|
button = button.replace('<b-button ',
|
||||||
'<b-button tag="a"')
|
'<b-button tag="a"')
|
||||||
button = HTML.literal(button)
|
button = HTML.literal(button)
|
||||||
|
@ -2733,7 +2699,7 @@ class MasterView(View):
|
||||||
btn_kw['icon_left'] = 'external-link-alt'
|
btn_kw['icon_left'] = 'external-link-alt'
|
||||||
btn_kw['target'] = '_blank'
|
btn_kw['target'] = '_blank'
|
||||||
button = HTML.tag('b-button', **btn_kw)
|
button = HTML.tag('b-button', **btn_kw)
|
||||||
button = six.text_type(button)
|
button = str(button)
|
||||||
button = button.replace('<b-button ',
|
button = button.replace('<b-button ',
|
||||||
'<b-button tag="a"')
|
'<b-button tag="a"')
|
||||||
button = HTML.literal(button)
|
button = HTML.literal(button)
|
||||||
|
@ -2840,9 +2806,7 @@ class MasterView(View):
|
||||||
return actions
|
return actions
|
||||||
|
|
||||||
def make_grid_action_view(self):
|
def make_grid_action_view(self):
|
||||||
use_buefy = self.get_use_buefy()
|
return self.make_action('view', icon='eye', url=self.default_view_url())
|
||||||
icon = 'eye' if use_buefy else 'zoomin'
|
|
||||||
return self.make_action('view', icon=icon, url=self.default_view_url())
|
|
||||||
|
|
||||||
def default_view_url(self):
|
def default_view_url(self):
|
||||||
if self.use_index_links:
|
if self.use_index_links:
|
||||||
|
@ -2869,18 +2833,15 @@ class MasterView(View):
|
||||||
return actions
|
return actions
|
||||||
|
|
||||||
def make_grid_action_edit(self):
|
def make_grid_action_edit(self):
|
||||||
use_buefy = self.get_use_buefy()
|
return self.make_action('edit', icon='edit', url=self.default_edit_url)
|
||||||
icon = 'edit' if use_buefy else 'pencil'
|
|
||||||
return self.make_action('edit', icon=icon, url=self.default_edit_url)
|
|
||||||
|
|
||||||
def make_grid_action_clone(self):
|
def make_grid_action_clone(self):
|
||||||
return self.make_action('clone', icon='object-ungroup',
|
return self.make_action('clone', icon='object-ungroup',
|
||||||
url=self.default_clone_url)
|
url=self.default_clone_url)
|
||||||
|
|
||||||
def make_grid_action_delete(self):
|
def make_grid_action_delete(self):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if use_buefy and self.delete_confirm == 'simple':
|
if self.delete_confirm == 'simple':
|
||||||
kwargs['click_handler'] = 'deleteObject'
|
kwargs['click_handler'] = 'deleteObject'
|
||||||
return self.make_action('delete', icon='trash', url=self.default_delete_url, **kwargs)
|
return self.make_action('delete', icon='trash', url=self.default_delete_url, **kwargs)
|
||||||
|
|
||||||
|
@ -2917,7 +2878,7 @@ class MasterView(View):
|
||||||
mapper = orm.object_mapper(row)
|
mapper = orm.object_mapper(row)
|
||||||
except orm.exc.UnmappedInstanceError:
|
except orm.exc.UnmappedInstanceError:
|
||||||
try:
|
try:
|
||||||
if isinstance(self.model_key, six.string_types):
|
if isinstance(self.model_key, str):
|
||||||
return {self.model_key: row[self.model_key]}
|
return {self.model_key: row[self.model_key]}
|
||||||
return dict([(key, row[key])
|
return dict([(key, row[key])
|
||||||
for key in self.model_key])
|
for key in self.model_key])
|
||||||
|
@ -3134,12 +3095,8 @@ class MasterView(View):
|
||||||
"""
|
"""
|
||||||
if fmt == 'csv':
|
if fmt == 'csv':
|
||||||
|
|
||||||
if six.PY2:
|
csv_file = open(path, 'wt', encoding='utf_8')
|
||||||
csv_file = open(path, 'wb')
|
writer = csv.DictWriter(csv_file, fields)
|
||||||
writer = UnicodeDictWriter(csv_file, fields, encoding='utf_8')
|
|
||||||
else: # PY3
|
|
||||||
csv_file = open(path, 'wt', encoding='utf_8')
|
|
||||||
writer = csv.DictWriter(csv_file, fields)
|
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
|
|
||||||
def write(obj, i):
|
def write(obj, i):
|
||||||
|
@ -3229,7 +3186,7 @@ class MasterView(View):
|
||||||
if value is None:
|
if value is None:
|
||||||
value = ''
|
value = ''
|
||||||
else:
|
else:
|
||||||
value = six.text_type(value)
|
value = str(value)
|
||||||
|
|
||||||
csvrow[field] = value
|
csvrow[field] = value
|
||||||
|
|
||||||
|
@ -3297,13 +3254,8 @@ class MasterView(View):
|
||||||
results = results.with_session(session).all()
|
results = results.with_session(session).all()
|
||||||
fields = self.get_csv_fields()
|
fields = self.get_csv_fields()
|
||||||
|
|
||||||
if six.PY2:
|
csv_file = open(path, 'wt', encoding='utf_8')
|
||||||
csv_file = open(path, 'wb')
|
writer = csv.DictWriter(csv_file, fields)
|
||||||
writer = UnicodeDictWriter(csv_file, fields, encoding='utf_8')
|
|
||||||
else: # PY3
|
|
||||||
csv_file = open(path, 'wt', encoding='utf_8')
|
|
||||||
writer = csv.DictWriter(csv_file, fields)
|
|
||||||
|
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
|
|
||||||
def write(obj, i):
|
def write(obj, i):
|
||||||
|
@ -3663,12 +3615,8 @@ class MasterView(View):
|
||||||
|
|
||||||
if fmt == 'csv':
|
if fmt == 'csv':
|
||||||
|
|
||||||
if six.PY2:
|
csv_file = open(path, 'wt', encoding='utf_8')
|
||||||
csv_file = open(path, 'wb')
|
writer = csv.DictWriter(csv_file, fields)
|
||||||
writer = UnicodeDictWriter(csv_file, fields, encoding='utf_8')
|
|
||||||
else: # PY3
|
|
||||||
csv_file = open(path, 'wt', encoding='utf_8')
|
|
||||||
writer = csv.DictWriter(csv_file, fields)
|
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
|
|
||||||
def write(obj, i):
|
def write(obj, i):
|
||||||
|
@ -3737,7 +3685,7 @@ class MasterView(View):
|
||||||
if value is None:
|
if value is None:
|
||||||
value = ''
|
value = ''
|
||||||
else:
|
else:
|
||||||
value = six.text_type(value)
|
value = str(value)
|
||||||
|
|
||||||
csvrow[field] = value
|
csvrow[field] = value
|
||||||
|
|
||||||
|
@ -3814,7 +3762,7 @@ class MasterView(View):
|
||||||
value = getattr(row, field, None)
|
value = getattr(row, field, None)
|
||||||
|
|
||||||
if isinstance(value, GPC):
|
if isinstance(value, GPC):
|
||||||
value = six.text_type(value)
|
value = str(value)
|
||||||
|
|
||||||
elif isinstance(value, datetime.datetime):
|
elif isinstance(value, datetime.datetime):
|
||||||
# datetime values we provide to Excel must *not* have time zone info,
|
# datetime values we provide to Excel must *not* have time zone info,
|
||||||
|
@ -3844,14 +3792,9 @@ class MasterView(View):
|
||||||
writer.writerow(self.get_row_csv_row(row, fields))
|
writer.writerow(self.get_row_csv_row(row, fields))
|
||||||
response = self.request.response
|
response = self.request.response
|
||||||
filename = self.get_row_results_csv_filename(obj)
|
filename = self.get_row_results_csv_filename(obj)
|
||||||
if six.PY3:
|
response.text = data.getvalue()
|
||||||
response.text = data.getvalue()
|
response.content_type = 'text/csv'
|
||||||
response.content_type = 'text/csv'
|
response.content_disposition = 'attachment; filename={}'.format(filename)
|
||||||
response.content_disposition = 'attachment; filename={}'.format(filename)
|
|
||||||
else:
|
|
||||||
response.body = data.getvalue()
|
|
||||||
response.content_type = b'text/csv'
|
|
||||||
response.content_disposition = b'attachment; filename={}'.format(filename)
|
|
||||||
data.close()
|
data.close()
|
||||||
response.content_length = len(response.body)
|
response.content_length = len(response.body)
|
||||||
return response
|
return response
|
||||||
|
@ -3898,7 +3841,7 @@ class MasterView(View):
|
||||||
if isinstance(value, datetime.datetime):
|
if isinstance(value, datetime.datetime):
|
||||||
# TODO: this assumes value is *always* naive UTC
|
# TODO: this assumes value is *always* naive UTC
|
||||||
value = localtime(self.rattail_config, value, from_utc=True)
|
value = localtime(self.rattail_config, value, from_utc=True)
|
||||||
csvrow[field] = '' if value is None else six.text_type(value)
|
csvrow[field] = '' if value is None else str(value)
|
||||||
return csvrow
|
return csvrow
|
||||||
|
|
||||||
def get_row_csv_row(self, row, fields):
|
def get_row_csv_row(self, row, fields):
|
||||||
|
@ -3911,7 +3854,7 @@ class MasterView(View):
|
||||||
if isinstance(value, datetime.datetime):
|
if isinstance(value, datetime.datetime):
|
||||||
# TODO: this assumes value is *always* naive UTC
|
# TODO: this assumes value is *always* naive UTC
|
||||||
value = localtime(self.rattail_config, value, from_utc=True)
|
value = localtime(self.rattail_config, value, from_utc=True)
|
||||||
csvrow[field] = '' if value is None else six.text_type(value)
|
csvrow[field] = '' if value is None else str(value)
|
||||||
return csvrow
|
return csvrow
|
||||||
|
|
||||||
##############################
|
##############################
|
||||||
|
@ -3966,7 +3909,7 @@ class MasterView(View):
|
||||||
"""
|
"""
|
||||||
Return a "pretty" title for the instance, to be used in the page title etc.
|
Return a "pretty" title for the instance, to be used in the page title etc.
|
||||||
"""
|
"""
|
||||||
return six.text_type(instance)
|
return str(instance)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_form_factory(cls):
|
def get_form_factory(cls):
|
||||||
|
@ -4078,7 +4021,6 @@ class MasterView(View):
|
||||||
'readonly': self.viewing,
|
'readonly': self.viewing,
|
||||||
'model_class': getattr(self, 'model_class', None),
|
'model_class': getattr(self, 'model_class', None),
|
||||||
'action_url': self.request.current_route_url(_query=None),
|
'action_url': self.request.current_route_url(_query=None),
|
||||||
'use_buefy': self.get_use_buefy(),
|
|
||||||
'assume_local_times': self.has_local_times,
|
'assume_local_times': self.has_local_times,
|
||||||
'route_prefix': route_prefix,
|
'route_prefix': route_prefix,
|
||||||
'can_edit_help': (self.has_perm('edit_help')
|
'can_edit_help': (self.has_perm('edit_help')
|
||||||
|
@ -4547,7 +4489,6 @@ class MasterView(View):
|
||||||
'readonly': self.viewing,
|
'readonly': self.viewing,
|
||||||
'model_class': getattr(self, 'model_row_class', None),
|
'model_class': getattr(self, 'model_row_class', None),
|
||||||
'action_url': self.request.current_route_url(_query=None),
|
'action_url': self.request.current_route_url(_query=None),
|
||||||
'use_buefy': self.get_use_buefy(),
|
|
||||||
}
|
}
|
||||||
if self.creating:
|
if self.creating:
|
||||||
kwargs.setdefault('cancel_url', self.request.get_referrer())
|
kwargs.setdefault('cancel_url', self.request.get_referrer())
|
||||||
|
@ -4644,7 +4585,7 @@ class MasterView(View):
|
||||||
|
|
||||||
# collect any uploaded files
|
# collect any uploaded files
|
||||||
uploads = {}
|
uploads = {}
|
||||||
for key, value in six.iteritems(data):
|
for key, value in data.items():
|
||||||
if isinstance(value, cgi_FieldStorage):
|
if isinstance(value, cgi_FieldStorage):
|
||||||
tempdir = tempfile.mkdtemp()
|
tempdir = tempfile.mkdtemp()
|
||||||
filename = os.path.basename(value.filename)
|
filename = os.path.basename(value.filename)
|
||||||
|
@ -4829,13 +4770,13 @@ class MasterView(View):
|
||||||
value = data.get(name)
|
value = data.get(name)
|
||||||
|
|
||||||
if simple.get('type') is bool:
|
if simple.get('type') is bool:
|
||||||
value = six.text_type(bool(value)).lower()
|
value = str(bool(value)).lower()
|
||||||
elif simple.get('type') is int:
|
elif simple.get('type') is int:
|
||||||
value = six.text_type(int(value or '0'))
|
value = str(int(value or '0'))
|
||||||
elif value is None:
|
elif value is None:
|
||||||
value = ''
|
value = ''
|
||||||
else:
|
else:
|
||||||
value = six.text_type(value)
|
value = str(value)
|
||||||
|
|
||||||
# only want to save this setting if we received a
|
# only want to save this setting if we received a
|
||||||
# value, or if empty values are okay to save
|
# value, or if empty values are okay to save
|
||||||
|
|
|
@ -24,8 +24,6 @@
|
||||||
Base class for Config Views
|
Base class for Config Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
@ -62,7 +60,6 @@ class MenuConfigView(View):
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'config_title': "Menus",
|
'config_title': "Menus",
|
||||||
'use_buefy': True,
|
|
||||||
'index_title': "App Details",
|
'index_title': "App Details",
|
||||||
'index_url': self.request.route_url('appinfo'),
|
'index_url': self.request.route_url('appinfo'),
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,6 @@
|
||||||
Message Views
|
Message Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.time import localtime
|
from rattail.time import localtime
|
||||||
|
|
||||||
|
@ -139,7 +135,7 @@ class MessageView(MasterView):
|
||||||
sender = message.sender
|
sender = message.sender
|
||||||
if sender is self.request.user:
|
if sender is self.request.user:
|
||||||
return 'you'
|
return 'you'
|
||||||
return six.text_type(sender)
|
return str(sender)
|
||||||
|
|
||||||
def render_subject_bold(self, message, field):
|
def render_subject_bold(self, message, field):
|
||||||
if not message.subject:
|
if not message.subject:
|
||||||
|
@ -164,8 +160,6 @@ class MessageView(MasterView):
|
||||||
if not recipients:
|
if not recipients:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# remove current user from displayed list, even if they're a recipient
|
# remove current user from displayed list, even if they're a recipient
|
||||||
recips = [r for r in recipients
|
recips = [r for r in recipients
|
||||||
if r.recipient is not self.request.user]
|
if r.recipient is not self.request.user]
|
||||||
|
@ -182,23 +176,17 @@ class MessageView(MasterView):
|
||||||
# client-side JS allowing the user to view all if they want
|
# client-side JS allowing the user to view all if they want
|
||||||
max_display = 5
|
max_display = 5
|
||||||
if len(recips) > max_display:
|
if len(recips) > max_display:
|
||||||
if use_buefy:
|
basic = HTML.tag('span', c="{}, ".format(', '.join(recips[:max_display-1])))
|
||||||
basic = HTML.tag('span', c="{}, ".format(', '.join(recips[:max_display-1])))
|
more = tags.link_to("({} more)".format(len(recips[max_display-1:])), '#', **{
|
||||||
more = tags.link_to("({} more)".format(len(recips[max_display-1:])), '#', **{
|
'v-show': '!showingAllRecipients',
|
||||||
'v-show': '!showingAllRecipients',
|
'@click.prevent': 'showMoreRecipients()',
|
||||||
'@click.prevent': 'showMoreRecipients()',
|
})
|
||||||
})
|
everyone = HTML.tag('span', c=', '.join(recips[max_display-1:]), **{
|
||||||
everyone = HTML.tag('span', c=', '.join(recips[max_display-1:]), **{
|
'v-show': 'showingAllRecipients',
|
||||||
'v-show': 'showingAllRecipients',
|
'@click': 'hideMoreRecipients()',
|
||||||
'@click': 'hideMoreRecipients()',
|
'class_': 'everyone',
|
||||||
'class_': 'everyone',
|
})
|
||||||
})
|
return HTML.tag('div', c=[basic, more, everyone])
|
||||||
return HTML.tag('div', c=[basic, more, everyone])
|
|
||||||
else:
|
|
||||||
basic = HTML.literal("{}, ".format(', '.join(recips[:max_display-1])))
|
|
||||||
more = tags.link_to("({} more)".format(len(recips[max_display-1:])), '#', class_='more')
|
|
||||||
everyone = HTML.tag('span', class_='everyone', c=', '.join(recips[max_display-1:]))
|
|
||||||
return basic + more + everyone
|
|
||||||
|
|
||||||
# show the full list if there are few enough recipients for that
|
# show the full list if there are few enough recipients for that
|
||||||
return ', '.join(recips)
|
return ', '.join(recips)
|
||||||
|
@ -214,15 +202,9 @@ class MessageView(MasterView):
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(MessageView, self).configure_form(f)
|
super(MessageView, self).configure_form(f)
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
f.submit_label = "Send Message"
|
f.submit_label = "Send Message"
|
||||||
|
|
||||||
if not use_buefy:
|
|
||||||
# we have custom logic to disable submit button
|
|
||||||
f.auto_disable = False
|
|
||||||
f.auto_disable_save = False
|
|
||||||
|
|
||||||
# TODO: A fair amount of this still seems hacky...
|
# TODO: A fair amount of this still seems hacky...
|
||||||
|
|
||||||
f.set_renderer('sender', self.render_sender)
|
f.set_renderer('sender', self.render_sender)
|
||||||
|
@ -235,13 +217,12 @@ class MessageView(MasterView):
|
||||||
f.set_label('recipients', "To")
|
f.set_label('recipients', "To")
|
||||||
|
|
||||||
# subject
|
# subject
|
||||||
if use_buefy:
|
f.set_renderer('subject', self.render_subject_bold)
|
||||||
f.set_renderer('subject', self.render_subject_bold)
|
if self.creating:
|
||||||
if self.creating:
|
f.set_widget('subject', dfwidget.TextInputWidget(
|
||||||
f.set_widget('subject', dfwidget.TextInputWidget(
|
placeholder="please enter a subject",
|
||||||
placeholder="please enter a subject",
|
autocomplete='off'))
|
||||||
autocomplete='off'))
|
f.set_required('subject')
|
||||||
f.set_required('subject')
|
|
||||||
|
|
||||||
# body
|
# body
|
||||||
f.set_widget('body', dfwidget.TextAreaWidget(cols=50, rows=15))
|
f.set_widget('body', dfwidget.TextAreaWidget(cols=50, rows=15))
|
||||||
|
@ -253,10 +234,7 @@ class MessageView(MasterView):
|
||||||
f.insert_after('recipients', 'set_recipients')
|
f.insert_after('recipients', 'set_recipients')
|
||||||
f.remove('recipients')
|
f.remove('recipients')
|
||||||
f.set_node('set_recipients', colander.SchemaNode(colander.Set()))
|
f.set_node('set_recipients', colander.SchemaNode(colander.Set()))
|
||||||
if use_buefy:
|
f.set_widget('set_recipients', RecipientsWidgetBuefy())
|
||||||
f.set_widget('set_recipients', RecipientsWidgetBuefy())
|
|
||||||
else:
|
|
||||||
f.set_widget('set_recipients', RecipientsWidget())
|
|
||||||
f.set_label('set_recipients', "To")
|
f.set_label('set_recipients', "To")
|
||||||
|
|
||||||
if self.replying:
|
if self.replying:
|
||||||
|
@ -278,17 +256,11 @@ class MessageView(MasterView):
|
||||||
value = [r[0] for r in value]
|
value = [r[0] for r in value]
|
||||||
if old_message.sender is not self.request.user and old_message.sender.active:
|
if old_message.sender is not self.request.user and old_message.sender.active:
|
||||||
value.insert(0, old_message.sender_uuid)
|
value.insert(0, old_message.sender_uuid)
|
||||||
if use_buefy:
|
f.set_default('set_recipients', value)
|
||||||
f.set_default('set_recipients', value)
|
|
||||||
else:
|
|
||||||
f.set_default('set_recipients', ','.join(value))
|
|
||||||
|
|
||||||
# Just a normal reply, to sender only.
|
# Just a normal reply, to sender only.
|
||||||
elif self.filter_reply_recipient(old_message.sender):
|
elif self.filter_reply_recipient(old_message.sender):
|
||||||
if use_buefy:
|
f.set_default('set_recipients', [old_message.sender.uuid])
|
||||||
f.set_default('set_recipients', [old_message.sender.uuid])
|
|
||||||
else:
|
|
||||||
f.set_default('set_recipients', old_message.sender.uuid)
|
|
||||||
|
|
||||||
# TODO?
|
# TODO?
|
||||||
# # Set focus to message body instead of recipients, when replying.
|
# # Set focus to message body instead of recipients, when replying.
|
||||||
|
@ -347,11 +319,9 @@ class MessageView(MasterView):
|
||||||
return recipient
|
return recipient
|
||||||
|
|
||||||
def template_kwargs_create(self, **kwargs):
|
def template_kwargs_create(self, **kwargs):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
recips = self.get_available_recipients()
|
recips = self.get_available_recipients()
|
||||||
if use_buefy:
|
kwargs['recipient_display_map'] = recips
|
||||||
kwargs['recipient_display_map'] = recips
|
|
||||||
recips = list(recips.items())
|
recips = list(recips.items())
|
||||||
recips.sort(key=self.recipient_sortkey)
|
recips.sort(key=self.recipient_sortkey)
|
||||||
kwargs['available_recipients'] = recips
|
kwargs['available_recipients'] = recips
|
||||||
|
@ -359,9 +329,8 @@ class MessageView(MasterView):
|
||||||
if self.replying:
|
if self.replying:
|
||||||
kwargs['original_message'] = self.get_instance()
|
kwargs['original_message'] = self.get_instance()
|
||||||
|
|
||||||
if use_buefy:
|
kwargs['index_url'] = None
|
||||||
kwargs['index_url'] = None
|
kwargs['index_title'] = "New Message"
|
||||||
kwargs['index_title'] = "New Message"
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def recipient_sortkey(self, recip):
|
def recipient_sortkey(self, recip):
|
||||||
|
@ -538,20 +507,6 @@ class SentView(MessageView):
|
||||||
default_active=True, default_verb='contains')
|
default_active=True, default_verb='contains')
|
||||||
|
|
||||||
|
|
||||||
class RecipientsWidget(dfwidget.TextInputWidget):
|
|
||||||
|
|
||||||
def deserialize(self, field, pstruct):
|
|
||||||
if pstruct is colander.null:
|
|
||||||
return []
|
|
||||||
elif not isinstance(pstruct, six.string_types):
|
|
||||||
raise colander.Invalid(field.schema, "Pstruct is not a string")
|
|
||||||
if self.strip:
|
|
||||||
pstruct = pstruct.strip()
|
|
||||||
if not pstruct:
|
|
||||||
return []
|
|
||||||
return pstruct.split(',')
|
|
||||||
|
|
||||||
|
|
||||||
class RecipientsWidgetBuefy(dfwidget.Widget):
|
class RecipientsWidgetBuefy(dfwidget.Widget):
|
||||||
"""
|
"""
|
||||||
Custom "message recipients" widget, for use with Buefy / Vue.js themes.
|
Custom "message recipients" widget, for use with Buefy / Vue.js themes.
|
||||||
|
@ -561,7 +516,7 @@ class RecipientsWidgetBuefy(dfwidget.Widget):
|
||||||
def deserialize(self, field, pstruct):
|
def deserialize(self, field, pstruct):
|
||||||
if pstruct is colander.null:
|
if pstruct is colander.null:
|
||||||
return colander.null
|
return colander.null
|
||||||
if not isinstance(pstruct, six.string_types):
|
if not isinstance(pstruct, str):
|
||||||
raise colander.Invalid(field.schema, "Pstruct is not a string")
|
raise colander.Invalid(field.schema, "Pstruct is not a string")
|
||||||
if not pstruct:
|
if not pstruct:
|
||||||
return colander.null
|
return colander.null
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,12 +24,9 @@
|
||||||
Person Views
|
Person Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import six
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
||||||
|
@ -165,13 +162,10 @@ class PersonView(MasterView):
|
||||||
.filter(model.MergePeopleRequest.merged == None)\
|
.filter(model.MergePeopleRequest.merged == None)\
|
||||||
.first()
|
.first()
|
||||||
if merge_request:
|
if merge_request:
|
||||||
use_buefy = self.get_use_buefy()
|
return HTML.tag('span',
|
||||||
if use_buefy:
|
class_='has-text-danger has-text-weight-bold',
|
||||||
return HTML.tag('span',
|
title="A merge has been requested for this person.",
|
||||||
class_='has-text-danger has-text-weight-bold',
|
c="MR")
|
||||||
title="A merge has been requested for this person.",
|
|
||||||
c="MR")
|
|
||||||
return "MR"
|
|
||||||
|
|
||||||
def get_instance(self):
|
def get_instance(self):
|
||||||
# TODO: I don't recall why this fallback check for a vendor contact
|
# TODO: I don't recall why this fallback check for a vendor contact
|
||||||
|
@ -335,7 +329,7 @@ class PersonView(MasterView):
|
||||||
employee = person.employee
|
employee = person.employee
|
||||||
if not employee:
|
if not employee:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(employee)
|
text = str(employee)
|
||||||
url = self.request.route_url('employees.view', uuid=employee.uuid)
|
url = self.request.route_url('employees.view', uuid=employee.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -346,7 +340,7 @@ class PersonView(MasterView):
|
||||||
items = []
|
items = []
|
||||||
for customer in customers:
|
for customer in customers:
|
||||||
customer = customer.customer
|
customer = customer.customer
|
||||||
text = six.text_type(customer)
|
text = str(customer)
|
||||||
if customer.number:
|
if customer.number:
|
||||||
text = "(#{}) {}".format(customer.number, text)
|
text = "(#{}) {}".format(customer.number, text)
|
||||||
elif customer.id:
|
elif customer.id:
|
||||||
|
@ -361,7 +355,7 @@ class PersonView(MasterView):
|
||||||
return ""
|
return ""
|
||||||
items = []
|
items = []
|
||||||
for member in members:
|
for member in members:
|
||||||
text = six.text_type(member)
|
text = str(member)
|
||||||
if member.number:
|
if member.number:
|
||||||
text = "(#{}) {}".format(member.number, text)
|
text = "(#{}) {}".format(member.number, text)
|
||||||
elif member.id:
|
elif member.id:
|
||||||
|
@ -371,7 +365,6 @@ class PersonView(MasterView):
|
||||||
return HTML.tag('ul', c=items)
|
return HTML.tag('ul', c=items)
|
||||||
|
|
||||||
def render_users(self, person, field):
|
def render_users(self, person, field):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
users = person.users
|
users = person.users
|
||||||
items = []
|
items = []
|
||||||
for user in users:
|
for user in users:
|
||||||
|
@ -381,11 +374,8 @@ class PersonView(MasterView):
|
||||||
if items:
|
if items:
|
||||||
return HTML.tag('ul', c=items)
|
return HTML.tag('ul', c=items)
|
||||||
elif self.viewing and self.request.has_perm('users.create'):
|
elif self.viewing and self.request.has_perm('users.create'):
|
||||||
if use_buefy:
|
return HTML.tag('b-button', type='is-primary', c="Make User",
|
||||||
return HTML.tag('b-button', type='is-primary', c="Make User",
|
**{'@click': 'clickMakeUser()'})
|
||||||
**{'@click': 'clickMakeUser()'})
|
|
||||||
else:
|
|
||||||
return HTML.tag('button', type='button', id='make-user', c="Make User")
|
|
||||||
else:
|
else:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
@ -428,8 +418,7 @@ class PersonView(MasterView):
|
||||||
'dynamic_content_title': self.get_context_content_title(person),
|
'dynamic_content_title': self.get_context_content_title(person),
|
||||||
}
|
}
|
||||||
|
|
||||||
use_buefy = self.get_use_buefy()
|
template = 'view_profile_buefy'
|
||||||
template = 'view_profile_buefy' if use_buefy else 'view_profile'
|
|
||||||
return self.render_to_response(template, context)
|
return self.render_to_response(template, context)
|
||||||
|
|
||||||
def get_customer_xref_buttons(self, person):
|
def get_customer_xref_buttons(self, person):
|
||||||
|
@ -524,7 +513,7 @@ class PersonView(MasterView):
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_context_content_title(self, person):
|
def get_context_content_title(self, person):
|
||||||
return six.text_type(person)
|
return str(person)
|
||||||
|
|
||||||
def get_context_address(self, address):
|
def get_context_address(self, address):
|
||||||
context = {
|
context = {
|
||||||
|
@ -534,7 +523,7 @@ class PersonView(MasterView):
|
||||||
'city': address.city,
|
'city': address.city,
|
||||||
'state': address.state,
|
'state': address.state,
|
||||||
'zipcode': address.zipcode,
|
'zipcode': address.zipcode,
|
||||||
'display': six.text_type(address),
|
'display': str(address),
|
||||||
}
|
}
|
||||||
|
|
||||||
model = self.model
|
model = self.model
|
||||||
|
@ -587,12 +576,12 @@ class PersonView(MasterView):
|
||||||
'number': member.number,
|
'number': member.number,
|
||||||
'id': member.id,
|
'id': member.id,
|
||||||
'active': member.active,
|
'active': member.active,
|
||||||
'joined': six.text_type(member.joined) if member.joined else None,
|
'joined': str(member.joined) if member.joined else None,
|
||||||
'withdrew': six.text_type(member.withdrew) if member.withdrew else None,
|
'withdrew': str(member.withdrew) if member.withdrew else None,
|
||||||
'customer_uuid': member.customer_uuid,
|
'customer_uuid': member.customer_uuid,
|
||||||
'customer_name': member.customer.name if member.customer else None,
|
'customer_name': member.customer.name if member.customer else None,
|
||||||
'person_uuid': member.person_uuid,
|
'person_uuid': member.person_uuid,
|
||||||
'display': six.text_type(member),
|
'display': str(member),
|
||||||
'person_display_name': member.person.display_name if member.person else None,
|
'person_display_name': member.person.display_name if member.person else None,
|
||||||
'view_url': self.request.route_url('members.view', uuid=member.uuid),
|
'view_url': self.request.route_url('members.view', uuid=member.uuid),
|
||||||
'view_profile_url': profile_url,
|
'view_profile_url': profile_url,
|
||||||
|
@ -614,8 +603,8 @@ class PersonView(MasterView):
|
||||||
for history in employee.sorted_history(reverse=True):
|
for history in employee.sorted_history(reverse=True):
|
||||||
data.append({
|
data.append({
|
||||||
'uuid': history.uuid,
|
'uuid': history.uuid,
|
||||||
'start_date': six.text_type(history.start_date),
|
'start_date': str(history.start_date),
|
||||||
'end_date': six.text_type(history.end_date or ''),
|
'end_date': str(history.end_date or ''),
|
||||||
})
|
})
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -911,7 +900,7 @@ class PersonView(MasterView):
|
||||||
'success': True,
|
'success': True,
|
||||||
'employee': self.get_context_employee(employee),
|
'employee': self.get_context_employee(employee),
|
||||||
'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid),
|
'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid),
|
||||||
'start_date': six.text_type(start_date),
|
'start_date': str(start_date),
|
||||||
'employee_history_data': self.get_context_employee_history(employee),
|
'employee_history_data': self.get_context_employee_history(employee),
|
||||||
'dynamic_content_title': self.get_context_content_title(person),
|
'dynamic_content_title': self.get_context_content_title(person),
|
||||||
}
|
}
|
||||||
|
@ -942,7 +931,7 @@ class PersonView(MasterView):
|
||||||
'success': True,
|
'success': True,
|
||||||
'employee': self.get_context_employee(employee),
|
'employee': self.get_context_employee(employee),
|
||||||
'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid),
|
'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid),
|
||||||
'end_date': six.text_type(end_date),
|
'end_date': str(end_date),
|
||||||
'employee_history_data': self.get_context_employee_history(employee),
|
'employee_history_data': self.get_context_employee_history(employee),
|
||||||
'dynamic_content_title': self.get_context_content_title(person),
|
'dynamic_content_title': self.get_context_content_title(person),
|
||||||
}
|
}
|
||||||
|
@ -975,8 +964,8 @@ class PersonView(MasterView):
|
||||||
return {
|
return {
|
||||||
'success': True,
|
'success': True,
|
||||||
'employee': self.get_context_employee(employee),
|
'employee': self.get_context_employee(employee),
|
||||||
'start_date': six.text_type(current_history.start_date),
|
'start_date': str(current_history.start_date),
|
||||||
'end_date': six.text_type(current_history.end_date or ''),
|
'end_date': str(current_history.end_date or ''),
|
||||||
'employee_history_data': self.get_context_employee_history(employee),
|
'employee_history_data': self.get_context_employee_history(employee),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1438,7 +1427,7 @@ class MergePeopleRequestView(MasterView):
|
||||||
uuid = getattr(merge_request, field)
|
uuid = getattr(merge_request, field)
|
||||||
person = self.Session.query(self.model.Person).get(uuid)
|
person = self.Session.query(self.model.Person).get(uuid)
|
||||||
if person:
|
if person:
|
||||||
return six.text_type(person)
|
return str(person)
|
||||||
return "(person not found)"
|
return "(person not found)"
|
||||||
|
|
||||||
def get_instance_title(self, merge_request):
|
def get_instance_title(self, merge_request):
|
||||||
|
@ -1459,7 +1448,7 @@ class MergePeopleRequestView(MasterView):
|
||||||
uuid = getattr(merge_request, field)
|
uuid = getattr(merge_request, field)
|
||||||
person = self.Session.query(self.model.Person).get(uuid)
|
person = self.Session.query(self.model.Person).get(uuid)
|
||||||
if person:
|
if person:
|
||||||
text = six.text_type(person)
|
text = str(person)
|
||||||
url = self.request.route_url('people.view', uuid=person.uuid)
|
url = self.request.route_url('people.view', uuid=person.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
return "(person not found)"
|
return "(person not found)"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2021 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,8 +24,6 @@
|
||||||
"Principal" master view
|
"Principal" master view
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from rattail.core import Object
|
from rattail.core import Object
|
||||||
|
@ -85,12 +83,11 @@ class PrincipalMasterView(MasterView):
|
||||||
|
|
||||||
context = {'form': form, 'permissions': sorted_perms, 'principals': principals}
|
context = {'form': form, 'permissions': sorted_perms, 'principals': principals}
|
||||||
|
|
||||||
if self.get_use_buefy():
|
perms = self.get_buefy_perms_data(sorted_perms)
|
||||||
perms = self.get_buefy_perms_data(sorted_perms)
|
context['buefy_perms'] = perms
|
||||||
context['buefy_perms'] = perms
|
context['buefy_sorted_groups'] = list(perms)
|
||||||
context['buefy_sorted_groups'] = list(perms)
|
context['selected_group'] = self.request.POST.get('permission_group', 'common')
|
||||||
context['selected_group'] = self.request.POST.get('permission_group', 'common')
|
context['selected_permission'] = self.request.POST.get('permission', None)
|
||||||
context['selected_permission'] = self.request.POST.get('permission', None)
|
|
||||||
|
|
||||||
return self.render_to_response('find_by_perm', context)
|
return self.render_to_response('find_by_perm', context)
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,9 @@
|
||||||
Product Views
|
Product Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import six
|
|
||||||
import humanize
|
import humanize
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
@ -212,7 +209,6 @@ class ProductView(MasterView):
|
||||||
super(ProductView, self).configure_grid(g)
|
super(ProductView, self).configure_grid(g)
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
model = self.model
|
model = self.model
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
def join_vendor(q):
|
def join_vendor(q):
|
||||||
return q.outerjoin(self.ProductVendorCost,
|
return q.outerjoin(self.ProductVendorCost,
|
||||||
|
@ -257,9 +253,6 @@ class ProductView(MasterView):
|
||||||
departments = self.get_departments()
|
departments = self.get_departments()
|
||||||
department_choices = OrderedDict([('', "(any)")]
|
department_choices = OrderedDict([('', "(any)")]
|
||||||
+ [(d.uuid, d.name) for d in departments])
|
+ [(d.uuid, d.name) for d in departments])
|
||||||
if not use_buefy:
|
|
||||||
department_choices = [tags.Option(name, uuid)
|
|
||||||
for uuid, name in six.iteritems(department_choices)]
|
|
||||||
g.set_filter('department', model.Department.uuid,
|
g.set_filter('department', model.Department.uuid,
|
||||||
value_enum=department_choices,
|
value_enum=department_choices,
|
||||||
verbs=['equal', 'not_equal', 'is_null', 'is_not_null', 'is_any'],
|
verbs=['equal', 'not_equal', 'is_null', 'is_not_null', 'is_any'],
|
||||||
|
@ -378,12 +371,9 @@ class ProductView(MasterView):
|
||||||
g.set_filter('report_code_name', model.ReportCode.name)
|
g.set_filter('report_code_name', model.ReportCode.name)
|
||||||
|
|
||||||
if self.expose_label_printing and self.has_perm('print_labels'):
|
if self.expose_label_printing and self.has_perm('print_labels'):
|
||||||
if use_buefy:
|
g.more_actions.append(self.make_action(
|
||||||
g.more_actions.append(self.make_action(
|
'print_label', icon='print', url='#',
|
||||||
'print_label', icon='print', url='#',
|
click_handler='quickLabelPrint(props.row)'))
|
||||||
click_handler='quickLabelPrint(props.row)'))
|
|
||||||
else:
|
|
||||||
g.more_actions.append(grids.GridAction('print_label', icon='print'))
|
|
||||||
|
|
||||||
g.set_renderer('regular_price', self.render_price)
|
g.set_renderer('regular_price', self.render_price)
|
||||||
g.set_renderer('on_hand', self.render_on_hand)
|
g.set_renderer('on_hand', self.render_on_hand)
|
||||||
|
@ -572,10 +562,7 @@ class ProductView(MasterView):
|
||||||
if not self.has_perm('versions'):
|
if not self.has_perm('versions'):
|
||||||
return text
|
return text
|
||||||
|
|
||||||
if self.get_use_buefy():
|
kwargs = {'@click.prevent': 'showPriceHistory_{}()'.format(typ)}
|
||||||
kwargs = {'@click.prevent': 'showPriceHistory_{}()'.format(typ)}
|
|
||||||
else:
|
|
||||||
kwargs = {'id': 'view-{}-price-history'.format(typ)}
|
|
||||||
history = tags.link_to("(view history)", '#', **kwargs)
|
history = tags.link_to("(view history)", '#', **kwargs)
|
||||||
if not text:
|
if not text:
|
||||||
return history
|
return history
|
||||||
|
@ -815,7 +802,7 @@ class ProductView(MasterView):
|
||||||
|
|
||||||
if 'upc' in data:
|
if 'upc' in data:
|
||||||
if isinstance(data['upc'], GPC):
|
if isinstance(data['upc'], GPC):
|
||||||
data['upc'] = six.text_type(data['upc'])
|
data['upc'] = str(data['upc'])
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -971,9 +958,9 @@ class ProductView(MasterView):
|
||||||
if self.request.POST.get('brand_uuid'):
|
if self.request.POST.get('brand_uuid'):
|
||||||
brand = self.Session.query(model.Brand).get(self.request.POST['brand_uuid'])
|
brand = self.Session.query(model.Brand).get(self.request.POST['brand_uuid'])
|
||||||
if brand:
|
if brand:
|
||||||
brand_display = six.text_type(brand)
|
brand_display = str(brand)
|
||||||
elif self.editing:
|
elif self.editing:
|
||||||
brand_display = six.text_type(product.brand or '')
|
brand_display = str(product.brand or '')
|
||||||
brands_url = self.request.route_url('brands.autocomplete')
|
brands_url = self.request.route_url('brands.autocomplete')
|
||||||
f.set_widget('brand_uuid', forms.widgets.JQueryAutocompleteWidget(
|
f.set_widget('brand_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||||
field_display=brand_display, service_url=brands_url))
|
field_display=brand_display, service_url=brands_url))
|
||||||
|
@ -1139,11 +1126,11 @@ class ProductView(MasterView):
|
||||||
history['price'] = float(price)
|
history['price'] = float(price)
|
||||||
history['price_display'] = app.render_currency(price)
|
history['price_display'] = app.render_currency(price)
|
||||||
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
|
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
|
||||||
history['changed'] = six.text_type(changed)
|
history['changed'] = str(changed)
|
||||||
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
|
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
|
||||||
user = history.pop('changed_by')
|
user = history.pop('changed_by')
|
||||||
history['changed_by_uuid'] = user.uuid if user else None
|
history['changed_by_uuid'] = user.uuid if user else None
|
||||||
history['changed_by_display'] = six.text_type(user or "??")
|
history['changed_by_display'] = str(user or "??")
|
||||||
jsdata.append(history)
|
jsdata.append(history)
|
||||||
return jsdata
|
return jsdata
|
||||||
|
|
||||||
|
@ -1165,18 +1152,17 @@ class ProductView(MasterView):
|
||||||
else:
|
else:
|
||||||
history['cost_display'] = None
|
history['cost_display'] = None
|
||||||
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
|
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
|
||||||
history['changed'] = six.text_type(changed)
|
history['changed'] = str(changed)
|
||||||
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
|
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
|
||||||
user = history.pop('changed_by')
|
user = history.pop('changed_by')
|
||||||
history['changed_by_uuid'] = user.uuid
|
history['changed_by_uuid'] = user.uuid
|
||||||
history['changed_by_display'] = six.text_type(user)
|
history['changed_by_display'] = str(user)
|
||||||
jsdata.append(history)
|
jsdata.append(history)
|
||||||
return jsdata
|
return jsdata
|
||||||
|
|
||||||
def template_kwargs_view(self, **kwargs):
|
def template_kwargs_view(self, **kwargs):
|
||||||
kwargs = super(ProductView, self).template_kwargs_view(**kwargs)
|
kwargs = super(ProductView, self).template_kwargs_view(**kwargs)
|
||||||
product = kwargs['instance']
|
product = kwargs['instance']
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
kwargs['image_url'] = self.products_handler.get_image_url(product)
|
kwargs['image_url'] = self.products_handler.get_image_url(product)
|
||||||
|
|
||||||
|
@ -1184,10 +1170,7 @@ class ProductView(MasterView):
|
||||||
if self.rattail_config.versioning_enabled() and self.has_perm('versions'):
|
if self.rattail_config.versioning_enabled() and self.has_perm('versions'):
|
||||||
|
|
||||||
# regular price
|
# regular price
|
||||||
if use_buefy:
|
data = [] # defer fetching until user asks for it
|
||||||
data = [] # defer fetching until user asks for it
|
|
||||||
else:
|
|
||||||
data = self.get_regular_price_history(product)
|
|
||||||
grid = grids.Grid('products.regular_price_history', data,
|
grid = grids.Grid('products.regular_price_history', data,
|
||||||
request=self.request,
|
request=self.request,
|
||||||
columns=[
|
columns=[
|
||||||
|
@ -1201,10 +1184,7 @@ class ProductView(MasterView):
|
||||||
kwargs['regular_price_history_grid'] = grid
|
kwargs['regular_price_history_grid'] = grid
|
||||||
|
|
||||||
# current price
|
# current price
|
||||||
if use_buefy:
|
data = [] # defer fetching until user asks for it
|
||||||
data = [] # defer fetching until user asks for it
|
|
||||||
else:
|
|
||||||
data = self.get_current_price_history(product)
|
|
||||||
grid = grids.Grid('products.current_price_history', data,
|
grid = grids.Grid('products.current_price_history', data,
|
||||||
request=self.request,
|
request=self.request,
|
||||||
columns=[
|
columns=[
|
||||||
|
@ -1222,10 +1202,7 @@ class ProductView(MasterView):
|
||||||
kwargs['current_price_history_grid'] = grid
|
kwargs['current_price_history_grid'] = grid
|
||||||
|
|
||||||
# suggested price
|
# suggested price
|
||||||
if use_buefy:
|
data = [] # defer fetching until user asks for it
|
||||||
data = [] # defer fetching until user asks for it
|
|
||||||
else:
|
|
||||||
data = self.get_suggested_price_history(product)
|
|
||||||
grid = grids.Grid('products.suggested_price_history', data,
|
grid = grids.Grid('products.suggested_price_history', data,
|
||||||
request=self.request,
|
request=self.request,
|
||||||
columns=[
|
columns=[
|
||||||
|
@ -1239,10 +1216,7 @@ class ProductView(MasterView):
|
||||||
kwargs['suggested_price_history_grid'] = grid
|
kwargs['suggested_price_history_grid'] = grid
|
||||||
|
|
||||||
# cost history
|
# cost history
|
||||||
if use_buefy:
|
data = [] # defer fetching until user asks for it
|
||||||
data = [] # defer fetching until user asks for it
|
|
||||||
else:
|
|
||||||
data = self.get_cost_history(product)
|
|
||||||
grid = grids.Grid('products.cost_history', data,
|
grid = grids.Grid('products.cost_history', data,
|
||||||
request=self.request,
|
request=self.request,
|
||||||
columns=[
|
columns=[
|
||||||
|
@ -1264,9 +1238,8 @@ class ProductView(MasterView):
|
||||||
kwargs['costs_label_code'] = "Order Code"
|
kwargs['costs_label_code'] = "Order Code"
|
||||||
kwargs['costs_label_case_size'] = "Case Size"
|
kwargs['costs_label_case_size'] = "Case Size"
|
||||||
|
|
||||||
if use_buefy:
|
kwargs['vendor_sources'] = self.get_context_vendor_sources(product)
|
||||||
kwargs['vendor_sources'] = self.get_context_vendor_sources(product)
|
kwargs['lookup_codes'] = self.get_context_lookup_codes(product)
|
||||||
kwargs['lookup_codes'] = self.get_context_lookup_codes(product)
|
|
||||||
|
|
||||||
kwargs['panel_fields'] = self.get_panel_fields(product)
|
kwargs['panel_fields'] = self.get_panel_fields(product)
|
||||||
|
|
||||||
|
@ -1362,7 +1335,7 @@ class ProductView(MasterView):
|
||||||
source['case_size'] = app.render_quantity(cost.case_size)
|
source['case_size'] = app.render_quantity(cost.case_size)
|
||||||
source['case_cost'] = app.render_currency(cost.case_cost)
|
source['case_cost'] = app.render_currency(cost.case_cost)
|
||||||
|
|
||||||
text = six.text_type(cost.vendor)
|
text = str(cost.vendor)
|
||||||
if link_vendor:
|
if link_vendor:
|
||||||
url = self.request.route_url('vendors.view', uuid=cost.vendor.uuid)
|
url = self.request.route_url('vendors.view', uuid=cost.vendor.uuid)
|
||||||
source['vendor'] = tags.link_to(text, url)
|
source['vendor'] = tags.link_to(text, url)
|
||||||
|
@ -1768,8 +1741,6 @@ class ProductView(MasterView):
|
||||||
# TODO: how to properly detect image type?
|
# TODO: how to properly detect image type?
|
||||||
# content_type = 'image/png'
|
# content_type = 'image/png'
|
||||||
content_type = 'image/jpeg'
|
content_type = 'image/jpeg'
|
||||||
if not six.PY3:
|
|
||||||
content_type = six.binary_type(content_type)
|
|
||||||
self.request.response.content_type = content_type
|
self.request.response.content_type = content_type
|
||||||
self.request.response.body = product.image.bytes
|
self.request.response.body = product.image.bytes
|
||||||
return self.request.response
|
return self.request.response
|
||||||
|
@ -1802,7 +1773,7 @@ class ProductView(MasterView):
|
||||||
printer.print_labels([({'product': product}, quantity)])
|
printer.print_labels([({'product': product}, quantity)])
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
log.warning("error occurred while printing labels", exc_info=True)
|
log.warning("error occurred while printing labels", exc_info=True)
|
||||||
return {'error': six.text_type(error)}
|
return {'error': str(error)}
|
||||||
return {'ok': True}
|
return {'ok': True}
|
||||||
|
|
||||||
def search(self):
|
def search(self):
|
||||||
|
@ -1923,7 +1894,7 @@ class ProductView(MasterView):
|
||||||
if product and (not product.deleted or self.request.has_perm('products.view_deleted')):
|
if product and (not product.deleted or self.request.has_perm('products.view_deleted')):
|
||||||
data = {
|
data = {
|
||||||
'uuid': product.uuid,
|
'uuid': product.uuid,
|
||||||
'upc': six.text_type(product.upc),
|
'upc': str(product.upc),
|
||||||
'upc_pretty': product.upc.pretty(),
|
'upc_pretty': product.upc.pretty(),
|
||||||
'full_description': product.full_description,
|
'full_description': product.full_description,
|
||||||
'image_url': pod.get_image_url(self.rattail_config, product.upc),
|
'image_url': pod.get_image_url(self.rattail_config, product.upc),
|
||||||
|
@ -2282,7 +2253,7 @@ class PendingProductView(MasterView):
|
||||||
g.set_enum('status_code', self.enum.PENDING_PRODUCT_STATUS)
|
g.set_enum('status_code', self.enum.PENDING_PRODUCT_STATUS)
|
||||||
g.filters['status_code'].default_active = True
|
g.filters['status_code'].default_active = True
|
||||||
g.filters['status_code'].default_verb = 'not_equal'
|
g.filters['status_code'].default_verb = 'not_equal'
|
||||||
g.filters['status_code'].default_value = six.text_type(self.enum.PENDING_PRODUCT_STATUS_RESOLVED)
|
g.filters['status_code'].default_value = str(self.enum.PENDING_PRODUCT_STATUS_RESOLVED)
|
||||||
|
|
||||||
g.set_sort_defaults('created', 'desc')
|
g.set_sort_defaults('created', 'desc')
|
||||||
|
|
||||||
|
@ -2317,9 +2288,9 @@ class PendingProductView(MasterView):
|
||||||
if self.request.POST.get('brand_uuid'):
|
if self.request.POST.get('brand_uuid'):
|
||||||
brand = self.Session.query(model.Brand).get(self.request.POST['brand_uuid'])
|
brand = self.Session.query(model.Brand).get(self.request.POST['brand_uuid'])
|
||||||
if brand:
|
if brand:
|
||||||
brand_display = six.text_type(brand)
|
brand_display = str(brand)
|
||||||
elif self.editing:
|
elif self.editing:
|
||||||
brand_display = six.text_type(pending.brand or '')
|
brand_display = str(pending.brand or '')
|
||||||
brands_url = self.request.route_url('brands.autocomplete')
|
brands_url = self.request.route_url('brands.autocomplete')
|
||||||
f.set_widget('brand_uuid', forms.widgets.JQueryAutocompleteWidget(
|
f.set_widget('brand_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||||
field_display=brand_display, service_url=brands_url))
|
field_display=brand_display, service_url=brands_url))
|
||||||
|
@ -2344,7 +2315,7 @@ class PendingProductView(MasterView):
|
||||||
if self.request.POST.get('vendor_uuid'):
|
if self.request.POST.get('vendor_uuid'):
|
||||||
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid'])
|
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid'])
|
||||||
if vendor:
|
if vendor:
|
||||||
vendor_display = six.text_type(vendor)
|
vendor_display = str(vendor)
|
||||||
f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget(
|
f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||||
field_display=vendor_display,
|
field_display=vendor_display,
|
||||||
service_url=self.request.route_url('vendors.autocomplete')))
|
service_url=self.request.route_url('vendors.autocomplete')))
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,8 +24,6 @@
|
||||||
Project views
|
Project views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
# from collections import OrderedDict
|
# from collections import OrderedDict
|
||||||
|
@ -160,7 +158,6 @@ class GenerateProjectView(View):
|
||||||
return RattailProjectHandler(self.rattail_config)
|
return RattailProjectHandler(self.rattail_config)
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# choices = OrderedDict([
|
# choices = OrderedDict([
|
||||||
# ('has_db', {'prompt': "Does project need its own Rattail DB?",
|
# ('has_db', {'prompt': "Does project need its own Rattail DB?",
|
||||||
|
@ -183,8 +180,7 @@ class GenerateProjectView(View):
|
||||||
schema = GenerateTailboneIntegrationProject
|
schema = GenerateTailboneIntegrationProject
|
||||||
else:
|
else:
|
||||||
schema = GenerateProject
|
schema = GenerateProject
|
||||||
form = forms.Form(schema=schema(), request=self.request,
|
form = forms.Form(schema=schema(), request=self.request)
|
||||||
use_buefy=use_buefy)
|
|
||||||
if form.validate(newstyle=True):
|
if form.validate(newstyle=True):
|
||||||
zipped = self.generate_project(project_type, form)
|
zipped = self.generate_project(project_type, form)
|
||||||
return self.file_response(zipped)
|
return self.file_response(zipped)
|
||||||
|
@ -195,7 +191,6 @@ class GenerateProjectView(View):
|
||||||
'index_title': "Generate Project",
|
'index_title': "Generate Project",
|
||||||
'handler': self.handler,
|
'handler': self.handler,
|
||||||
# 'choices': choices,
|
# 'choices': choices,
|
||||||
'use_buefy': use_buefy,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def generate_project(self, project_type, form):
|
def generate_project(self, project_type, form):
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,10 +24,6 @@
|
||||||
Base class for purchasing batch views
|
Base class for purchasing batch views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
import six
|
|
||||||
|
|
||||||
from rattail.db import model, api
|
from rattail.db import model, api
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
|
@ -230,7 +226,6 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
batch = f.model_instance
|
batch = f.model_instance
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
today = app.localtime().date()
|
today = app.localtime().date()
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
|
|
||||||
# mode
|
# mode
|
||||||
f.set_enum('mode', self.enum.PURCHASE_BATCH_MODE)
|
f.set_enum('mode', self.enum.PURCHASE_BATCH_MODE)
|
||||||
|
@ -278,7 +273,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
if self.request.POST.get('vendor_uuid'):
|
if self.request.POST.get('vendor_uuid'):
|
||||||
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid'])
|
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid'])
|
||||||
if vendor:
|
if vendor:
|
||||||
vendor_display = six.text_type(vendor)
|
vendor_display = str(vendor)
|
||||||
vendors_url = self.request.route_url('vendors.autocomplete')
|
vendors_url = self.request.route_url('vendors.autocomplete')
|
||||||
f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget(
|
f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||||
field_display=vendor_display, service_url=vendors_url))
|
field_display=vendor_display, service_url=vendors_url))
|
||||||
|
@ -311,14 +306,14 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
if self.request.POST.get('buyer_uuid'):
|
if self.request.POST.get('buyer_uuid'):
|
||||||
buyer = self.Session.query(model.Employee).get(self.request.POST['buyer_uuid'])
|
buyer = self.Session.query(model.Employee).get(self.request.POST['buyer_uuid'])
|
||||||
if buyer:
|
if buyer:
|
||||||
buyer_display = six.text_type(buyer)
|
buyer_display = str(buyer)
|
||||||
elif self.creating:
|
elif self.creating:
|
||||||
buyer = self.request.user.employee
|
buyer = self.request.user.employee
|
||||||
if buyer:
|
if buyer:
|
||||||
buyer_display = six.text_type(buyer)
|
buyer_display = str(buyer)
|
||||||
f.set_default('buyer_uuid', buyer.uuid)
|
f.set_default('buyer_uuid', buyer.uuid)
|
||||||
elif self.editing:
|
elif self.editing:
|
||||||
buyer_display = six.text_type(batch.buyer or '')
|
buyer_display = str(batch.buyer or '')
|
||||||
buyers_url = self.request.route_url('employees.autocomplete')
|
buyers_url = self.request.route_url('employees.autocomplete')
|
||||||
f.set_widget('buyer_uuid', forms.widgets.JQueryAutocompleteWidget(
|
f.set_widget('buyer_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||||
field_display=buyer_display, service_url=buyers_url))
|
field_display=buyer_display, service_url=buyers_url))
|
||||||
|
@ -346,11 +341,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
if len(parsers) == 1:
|
if len(parsers) == 1:
|
||||||
f.set_default('invoice_parser_key', parsers[0].key)
|
f.set_default('invoice_parser_key', parsers[0].key)
|
||||||
|
|
||||||
if use_buefy:
|
f.set_widget('invoice_parser_key', dfwidget.SelectWidget(values=parser_values))
|
||||||
f.set_widget('invoice_parser_key', dfwidget.SelectWidget(values=parser_values))
|
|
||||||
else:
|
|
||||||
parser_values.insert(0, ('', "(please choose)"))
|
|
||||||
f.set_widget('invoice_parser_key', forms.widgets.JQuerySelectWidget(values=parser_values))
|
|
||||||
else:
|
else:
|
||||||
f.remove_field('invoice_parser_key')
|
f.remove_field('invoice_parser_key')
|
||||||
|
|
||||||
|
@ -422,7 +413,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
purchase = batch.purchase
|
purchase = batch.purchase
|
||||||
if not purchase:
|
if not purchase:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(purchase)
|
text = str(purchase)
|
||||||
url = self.request.route_url('purchases.view', uuid=purchase.uuid)
|
url = self.request.route_url('purchases.view', uuid=purchase.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
|
@ -435,7 +426,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
|
|
||||||
def render_vendor_contact(self, batch, field):
|
def render_vendor_contact(self, batch, field):
|
||||||
if batch.vendor.contact:
|
if batch.vendor.contact:
|
||||||
return six.text_type(batch.vendor.contact)
|
return str(batch.vendor.contact)
|
||||||
|
|
||||||
def render_vendor_phone(self, batch, field):
|
def render_vendor_phone(self, batch, field):
|
||||||
return self.get_vendor_phone_number(batch)
|
return self.get_vendor_phone_number(batch)
|
||||||
|
@ -455,7 +446,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
employee = batch.buyer
|
employee = batch.buyer
|
||||||
if not employee:
|
if not employee:
|
||||||
return ""
|
return ""
|
||||||
text = six.text_type(employee)
|
text = str(employee)
|
||||||
if self.request.has_perm('employees.view'):
|
if self.request.has_perm('employees.view'):
|
||||||
url = self.request.route_url('employees.view', uuid=employee.uuid)
|
url = self.request.route_url('employees.view', uuid=employee.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
@ -484,7 +475,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
|
|
||||||
def get_buyer_values(self):
|
def get_buyer_values(self):
|
||||||
buyers = self.get_buyers()
|
buyers = self.get_buyers()
|
||||||
return [(b.uuid, six.text_type(b))
|
return [(b.uuid, str(b))
|
||||||
for b in buyers]
|
for b in buyers]
|
||||||
|
|
||||||
def get_department_options(self):
|
def get_department_options(self):
|
||||||
|
@ -802,13 +793,12 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
return app.render_cases_units(cases, units)
|
return app.render_cases_units(cases, units)
|
||||||
|
|
||||||
def make_row_credits_grid(self, row):
|
def make_row_credits_grid(self, row):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
route_prefix = self.get_route_prefix()
|
route_prefix = self.get_route_prefix()
|
||||||
factory = self.get_grid_factory()
|
factory = self.get_grid_factory()
|
||||||
|
|
||||||
g = factory(
|
g = factory(
|
||||||
key='{}.row_credits'.format(route_prefix),
|
key='{}.row_credits'.format(route_prefix),
|
||||||
data=[] if use_buefy else row.credits,
|
data=[],
|
||||||
columns=[
|
columns=[
|
||||||
'credit_type',
|
'credit_type',
|
||||||
'shorted',
|
'shorted',
|
||||||
|
@ -837,17 +827,9 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
return g
|
return g
|
||||||
|
|
||||||
def render_row_credits(self, row, field):
|
def render_row_credits(self, row, field):
|
||||||
use_buefy = self.get_use_buefy()
|
|
||||||
if not use_buefy and not row.credits:
|
|
||||||
return
|
|
||||||
|
|
||||||
g = self.make_row_credits_grid(row)
|
g = self.make_row_credits_grid(row)
|
||||||
|
return HTML.literal(
|
||||||
if use_buefy:
|
g.render_buefy_table_element(data_prop='rowData.credits'))
|
||||||
return HTML.literal(
|
|
||||||
g.render_buefy_table_element(data_prop='rowData.credits'))
|
|
||||||
else:
|
|
||||||
return HTML.literal(g.render_grid())
|
|
||||||
|
|
||||||
# def item_lookup(self, value, field=None):
|
# def item_lookup(self, value, field=None):
|
||||||
# """
|
# """
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue