Fix Buefy "row grids" when viewing parent; add basic file upload support
This commit is contained in:
parent
5998941741
commit
d7c8b80da5
|
@ -3,5 +3,3 @@ let TailboneForm = {
|
||||||
template: '#tailbone-form-template',
|
template: '#tailbone-form-template',
|
||||||
methods: {}
|
methods: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let TailboneFormData = {}
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ const OnceButton = {
|
||||||
'<b-button',
|
'<b-button',
|
||||||
':type="type"',
|
':type="type"',
|
||||||
':native-type="nativeType"',
|
':native-type="nativeType"',
|
||||||
|
':tag="tag"',
|
||||||
|
':href="href"',
|
||||||
|
':title="title"',
|
||||||
':disabled="disabled"',
|
':disabled="disabled"',
|
||||||
'@click="clicked"',
|
'@click="clicked"',
|
||||||
'>',
|
'>',
|
||||||
|
@ -15,7 +18,10 @@ const OnceButton = {
|
||||||
props: {
|
props: {
|
||||||
type: String,
|
type: String,
|
||||||
nativeType: String,
|
nativeType: String,
|
||||||
|
tag: String,
|
||||||
|
href: String,
|
||||||
text: String,
|
text: String,
|
||||||
|
title: String,
|
||||||
working: String,
|
working: String,
|
||||||
workingText: String,
|
workingText: String,
|
||||||
disabled: Boolean
|
disabled: Boolean
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2018 Lance Edgar
|
# Copyright © 2010-2019 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -34,6 +34,8 @@ import rattail
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
from rattail.db.auth import cache_permissions
|
from rattail.db.auth import cache_permissions
|
||||||
|
|
||||||
|
import colander
|
||||||
|
import deform
|
||||||
from pyramid import threadlocal
|
from pyramid import threadlocal
|
||||||
from webhelpers2.html import tags
|
from webhelpers2.html import tags
|
||||||
|
|
||||||
|
@ -97,6 +99,8 @@ def before_render(event):
|
||||||
renderer_globals['six'] = six
|
renderer_globals['six'] = six
|
||||||
renderer_globals['json'] = json
|
renderer_globals['json'] = json
|
||||||
renderer_globals['datetime'] = datetime
|
renderer_globals['datetime'] = datetime
|
||||||
|
renderer_globals['colander'] = colander
|
||||||
|
renderer_globals['deform'] = deform
|
||||||
|
|
||||||
# theme - we only want do this for classic web app, *not* API
|
# theme - we only want do this for classic web app, *not* API
|
||||||
# TODO: so, clearly we need a better way to distinguish the two
|
# TODO: so, clearly we need a better way to distinguish the two
|
||||||
|
|
|
@ -63,10 +63,10 @@
|
||||||
% if master.batch_refreshable(batch) and request.has_perm('{}.refresh'.format(permission_prefix)):
|
% if master.batch_refreshable(batch) and request.has_perm('{}.refresh'.format(permission_prefix)):
|
||||||
% if use_buefy:
|
% if use_buefy:
|
||||||
## TODO: this should surely use a POST request?
|
## TODO: this should surely use a POST request?
|
||||||
<a class="button"
|
<once-button tag="a"
|
||||||
href="${url('{}.refresh'.format(route_prefix), uuid=batch.uuid)}">
|
href="${url('{}.refresh'.format(route_prefix), uuid=batch.uuid)}"
|
||||||
Refresh Data
|
text="Refresh Data">
|
||||||
</a>
|
</once-button>
|
||||||
% else:
|
% else:
|
||||||
<button type="button" class="button" id="refresh-data">Refresh Data</button>
|
<button type="button" class="button" id="refresh-data">Refresh Data</button>
|
||||||
% endif
|
% endif
|
||||||
|
@ -74,17 +74,16 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="execute_submit_button()">
|
<%def name="execute_submit_button()">
|
||||||
<button type="submit"
|
<once-button type="is-primary"
|
||||||
class="button is-primary"
|
native-type="submit"
|
||||||
% if not execute_enabled:
|
% if not execute_enabled:
|
||||||
disabled="disabled"
|
disabled
|
||||||
% endif
|
% endif
|
||||||
% if why_not_execute:
|
% if why_not_execute:
|
||||||
title="${why_not_execute}"
|
title="${why_not_execute}"
|
||||||
% endif
|
% endif
|
||||||
>
|
text="${execute_title}">
|
||||||
${execute_title}
|
</once-button>
|
||||||
</button>
|
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="execute_button()">
|
<%def name="execute_button()">
|
||||||
|
@ -145,30 +144,21 @@
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-between;">
|
<%def name="render_form()">
|
||||||
|
## TODO: should use self.render_form_buttons()
|
||||||
|
## ${form.render(form_id='batch-form', buttons=capture(self.render_form_buttons))|n}
|
||||||
|
${form.render(form_id='batch-form', buttons=capture(buttons))|n}
|
||||||
|
</%def>
|
||||||
|
|
||||||
<div class="form-wrapper">
|
|
||||||
${form.render(form_id='batch-form', buttons=capture(buttons))|n}
|
|
||||||
</div><!-- form-wrapper -->
|
|
||||||
|
|
||||||
<div style="display: flex; align-items: flex-start;">
|
${self.render_form_complete()}
|
||||||
|
|
||||||
<div class="object-helpers">
|
|
||||||
${self.object_helpers()}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul id="context-menu">
|
|
||||||
${self.context_menu_items()}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
% if use_buefy:
|
% if use_buefy:
|
||||||
<br /><br />
|
<br /><br />
|
||||||
## TODO: stop using |n filter
|
## TODO: stop using |n filter
|
||||||
${rows_grid.render_buefy(allow_save_defaults=False, tools=rows_grid_tools)|n}
|
${rows_grid.render_buefy(allow_save_defaults=False, tools=rows_grid_tools)|n}
|
||||||
|
${self.make_tailbone_form_app()}
|
||||||
|
${self.make_tailbone_grid_app()}
|
||||||
% else:
|
% else:
|
||||||
## no buefy, so do the traditional thing
|
## no buefy, so do the traditional thing
|
||||||
${rows_grid|n}
|
${rows_grid|n}
|
||||||
|
|
43
tailbone/templates/deform/file_upload.pt
Normal file
43
tailbone/templates/deform/file_upload.pt
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<!-- -*- mode: html; -*- -->
|
||||||
|
<tal:block tal:define="oid oid|field.oid;
|
||||||
|
css_class css_class|field.widget.css_class;
|
||||||
|
style style|field.widget.style;
|
||||||
|
field_name field_name|field.name;
|
||||||
|
use_buefy use_buefy|0;">
|
||||||
|
|
||||||
|
<div tal:condition="not use_buefy" tal:omit-tag="">
|
||||||
|
${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;"
|
||||||
|
tal:omit-tag="">
|
||||||
|
${field.start_mapping()}
|
||||||
|
<b-upload name="upload"
|
||||||
|
v-model="${vmodel}">
|
||||||
|
<a class="button is-primary">
|
||||||
|
<b-icon pack="fas" icon="upload"></b-icon>
|
||||||
|
<span>Click to upload</span>
|
||||||
|
</a>
|
||||||
|
</b-upload>
|
||||||
|
<span class="file-name" v-if="${vmodel}">
|
||||||
|
{{ ${vmodel}.name }}
|
||||||
|
</span>
|
||||||
|
${field.end_mapping()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</tal:block>
|
|
@ -18,7 +18,7 @@
|
||||||
${self.render_form()}
|
${self.render_form()}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="display: flex;">
|
<div style="display: flex; align-items: flex-start;">
|
||||||
<div class="object-helpers">
|
<div class="object-helpers">
|
||||||
${self.object_helpers()}
|
${self.object_helpers()}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
|
|
||||||
<b-field horizontal
|
<b-field horizontal
|
||||||
label="${form.get_label(field.name)}"
|
label="${form.get_label(field.name)}"
|
||||||
|
## TODO: is this class="file" really needed?
|
||||||
|
% if isinstance(field.schema.typ, deform.FileData):
|
||||||
|
class="file"
|
||||||
|
% 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}'
|
||||||
|
@ -58,6 +62,28 @@
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
let TailboneFormData = {
|
||||||
|
|
||||||
|
## TODO: ugh, this seems pretty hacky. need to declare some data models
|
||||||
|
## for various field components to bind to...
|
||||||
|
% if not form.readonly:
|
||||||
|
% for field in form.fields:
|
||||||
|
% if field in dform:
|
||||||
|
<% field = dform[field] %>
|
||||||
|
% if isinstance(field.schema.typ, colander.Date):
|
||||||
|
field_model_${field.name}: null,
|
||||||
|
% elif isinstance(field.schema.typ, deform.FileData):
|
||||||
|
field_model_${field.name}: null,
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
% endif
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div id="tailbone-form-app">
|
<div id="tailbone-form-app">
|
||||||
<tailbone-form></tailbone-form>
|
<tailbone-form></tailbone-form>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
% if master.has_rows:
|
% if master.has_rows:
|
||||||
% if use_buefy:
|
% if use_buefy:
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.gridfilters.js') + '?ver={}'.format(tailbone.__version__))}
|
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.grid.js') + '?ver={}'.format(tailbone.__version__))}
|
||||||
% else:
|
% else:
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
|
@ -69,6 +69,25 @@
|
||||||
${rows_grid_tools}
|
${rows_grid_tools}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="modify_tailbone_grid()">
|
||||||
|
## NOTE: if you override this, must use <script> tags
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="make_tailbone_grid_app()">
|
||||||
|
${self.modify_tailbone_grid()}
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
TailboneGrid.data = function() { return TailboneGridData }
|
||||||
|
|
||||||
|
Vue.component('tailbone-grid', TailboneGrid)
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#tailbone-grid-app'
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
${self.render_form_complete()}
|
${self.render_form_complete()}
|
||||||
|
|
||||||
|
@ -77,12 +96,13 @@ ${self.render_form_complete()}
|
||||||
<br /><br />
|
<br /><br />
|
||||||
## TODO: stop using |n filter
|
## TODO: stop using |n filter
|
||||||
${rows_grid.render_buefy(allow_save_defaults=False, tools=capture(self.render_row_grid_tools))|n}
|
${rows_grid.render_buefy(allow_save_defaults=False, tools=capture(self.render_row_grid_tools))|n}
|
||||||
|
${self.make_tailbone_grid_app()}
|
||||||
% else:
|
% else:
|
||||||
## no buefy, so do the traditional thing
|
## no buefy, so do the traditional thing
|
||||||
${rows_grid|n}
|
${rows_grid|n}
|
||||||
% endif
|
% endif
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
% if form.use_buefy:
|
% if use_buefy:
|
||||||
${self.make_tailbone_form_app()}
|
${self.make_tailbone_form_app()}
|
||||||
% endif
|
% endif
|
||||||
|
|
Loading…
Reference in a new issue