Fix Buefy "row grids" when viewing parent; add basic file upload support
This commit is contained in:
		
							parent
							
								
									5998941741
								
							
						
					
					
						commit
						d7c8b80da5
					
				
					 8 changed files with 125 additions and 38 deletions
				
			
		| 
						 | 
				
			
			@ -3,5 +3,3 @@ let TailboneForm = {
 | 
			
		|||
    template: '#tailbone-form-template',
 | 
			
		||||
    methods: {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
let TailboneFormData = {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,9 @@ const OnceButton = {
 | 
			
		|||
        '<b-button',
 | 
			
		||||
        ':type="type"',
 | 
			
		||||
        ':native-type="nativeType"',
 | 
			
		||||
        ':tag="tag"',
 | 
			
		||||
        ':href="href"',
 | 
			
		||||
        ':title="title"',
 | 
			
		||||
        ':disabled="disabled"',
 | 
			
		||||
        '@click="clicked"',
 | 
			
		||||
        '>',
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +18,10 @@ const OnceButton = {
 | 
			
		|||
    props: {
 | 
			
		||||
        type: String,
 | 
			
		||||
        nativeType: String,
 | 
			
		||||
        tag: String,
 | 
			
		||||
        href: String,
 | 
			
		||||
        text: String,
 | 
			
		||||
        title: String,
 | 
			
		||||
        working: String,
 | 
			
		||||
        workingText: String,
 | 
			
		||||
        disabled: Boolean
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  Rattail -- Retail Software Framework
 | 
			
		||||
#  Copyright © 2010-2018 Lance Edgar
 | 
			
		||||
#  Copyright © 2010-2019 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of Rattail.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +34,8 @@ import rattail
 | 
			
		|||
from rattail.db import model
 | 
			
		||||
from rattail.db.auth import cache_permissions
 | 
			
		||||
 | 
			
		||||
import colander
 | 
			
		||||
import deform
 | 
			
		||||
from pyramid import threadlocal
 | 
			
		||||
from webhelpers2.html import tags
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +99,8 @@ def before_render(event):
 | 
			
		|||
    renderer_globals['six'] = six
 | 
			
		||||
    renderer_globals['json'] = json
 | 
			
		||||
    renderer_globals['datetime'] = datetime
 | 
			
		||||
    renderer_globals['colander'] = colander
 | 
			
		||||
    renderer_globals['deform'] = deform
 | 
			
		||||
 | 
			
		||||
    # theme  - we only want do this for classic web app, *not* API
 | 
			
		||||
    # 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 use_buefy:
 | 
			
		||||
          ## TODO: this should surely use a POST request?
 | 
			
		||||
          <a class="button"
 | 
			
		||||
             href="${url('{}.refresh'.format(route_prefix), uuid=batch.uuid)}">
 | 
			
		||||
            Refresh Data
 | 
			
		||||
          </a>
 | 
			
		||||
          <once-button tag="a"
 | 
			
		||||
                       href="${url('{}.refresh'.format(route_prefix), uuid=batch.uuid)}"
 | 
			
		||||
                       text="Refresh Data">
 | 
			
		||||
          </once-button>
 | 
			
		||||
      % else:
 | 
			
		||||
          <button type="button" class="button" id="refresh-data">Refresh Data</button>
 | 
			
		||||
      % endif
 | 
			
		||||
| 
						 | 
				
			
			@ -74,17 +74,16 @@
 | 
			
		|||
</%def>
 | 
			
		||||
 | 
			
		||||
<%def name="execute_submit_button()">
 | 
			
		||||
  <button type="submit"
 | 
			
		||||
          class="button is-primary"
 | 
			
		||||
          % if not execute_enabled:
 | 
			
		||||
          disabled="disabled"
 | 
			
		||||
          % endif
 | 
			
		||||
          % if why_not_execute:
 | 
			
		||||
          title="${why_not_execute}"
 | 
			
		||||
          % endif
 | 
			
		||||
          >
 | 
			
		||||
    ${execute_title}
 | 
			
		||||
  </button>
 | 
			
		||||
  <once-button type="is-primary"
 | 
			
		||||
               native-type="submit"
 | 
			
		||||
               % if not execute_enabled:
 | 
			
		||||
               disabled
 | 
			
		||||
               % endif
 | 
			
		||||
               % if why_not_execute:
 | 
			
		||||
               title="${why_not_execute}"
 | 
			
		||||
               % endif
 | 
			
		||||
               text="${execute_title}">
 | 
			
		||||
  </once-button>
 | 
			
		||||
</%def>
 | 
			
		||||
 | 
			
		||||
<%def name="execute_button()">
 | 
			
		||||
| 
						 | 
				
			
			@ -145,30 +144,21 @@
 | 
			
		|||
  % endif
 | 
			
		||||
</%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;">
 | 
			
		||||
 | 
			
		||||
    <div class="object-helpers">
 | 
			
		||||
      ${self.object_helpers()}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <ul id="context-menu">
 | 
			
		||||
      ${self.context_menu_items()}
 | 
			
		||||
    </ul>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
${self.render_form_complete()}
 | 
			
		||||
 | 
			
		||||
% if use_buefy:
 | 
			
		||||
    <br /><br />
 | 
			
		||||
    ## TODO: stop using |n filter
 | 
			
		||||
    ${rows_grid.render_buefy(allow_save_defaults=False, tools=rows_grid_tools)|n}
 | 
			
		||||
    ${self.make_tailbone_form_app()}
 | 
			
		||||
    ${self.make_tailbone_grid_app()}
 | 
			
		||||
% else:
 | 
			
		||||
    ## no buefy, so do the traditional thing
 | 
			
		||||
    ${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()}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div style="display: flex;">
 | 
			
		||||
    <div style="display: flex; align-items: flex-start;">
 | 
			
		||||
      <div class="object-helpers">
 | 
			
		||||
        ${self.object_helpers()}
 | 
			
		||||
      </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,10 @@
 | 
			
		|||
 | 
			
		||||
            <b-field horizontal
 | 
			
		||||
                     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:
 | 
			
		||||
                     type="is-danger"
 | 
			
		||||
                     :message='${form.messages_json(field.error.messages())|n}'
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +62,28 @@
 | 
			
		|||
  </div>
 | 
			
		||||
</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">
 | 
			
		||||
  <tailbone-form></tailbone-form>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
  ${parent.extra_javascript()}
 | 
			
		||||
  % if master.has_rows:
 | 
			
		||||
      % 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:
 | 
			
		||||
      <script type="text/javascript">
 | 
			
		||||
        $(function() {
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +69,25 @@
 | 
			
		|||
  ${rows_grid_tools}
 | 
			
		||||
</%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()}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -77,12 +96,13 @@ ${self.render_form_complete()}
 | 
			
		|||
        <br /><br />
 | 
			
		||||
        ## TODO: stop using |n filter
 | 
			
		||||
        ${rows_grid.render_buefy(allow_save_defaults=False, tools=capture(self.render_row_grid_tools))|n}
 | 
			
		||||
        ${self.make_tailbone_grid_app()}
 | 
			
		||||
    % else:
 | 
			
		||||
        ## no buefy, so do the traditional thing
 | 
			
		||||
        ${rows_grid|n}
 | 
			
		||||
    % endif
 | 
			
		||||
% endif
 | 
			
		||||
 | 
			
		||||
% if form.use_buefy:
 | 
			
		||||
% if use_buefy:
 | 
			
		||||
    ${self.make_tailbone_form_app()}
 | 
			
		||||
% endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue