Add support for Buefy autocomplete; several other form tweaks
at least the Edit User form should work now, for instance
This commit is contained in:
parent
d7e19865de
commit
2b6d88105c
|
@ -760,6 +760,29 @@ class Form(object):
|
||||||
context['render_field_readonly'] = self.render_field_readonly
|
context['render_field_readonly'] = self.render_field_readonly
|
||||||
return render(template, context)
|
return render(template, context)
|
||||||
|
|
||||||
|
def get_vuejs_model_value(self, field):
|
||||||
|
"""
|
||||||
|
This method must return "raw" JS which will be assigned as the initial
|
||||||
|
model value for the given field. This JS will be written as part of
|
||||||
|
the overall response, to be interpreted on the client side.
|
||||||
|
"""
|
||||||
|
if isinstance(field.schema.typ, colander.Date):
|
||||||
|
# TODO: don't recall why "always null" here?
|
||||||
|
return 'null'
|
||||||
|
|
||||||
|
if isinstance(field.schema.typ, deform.FileData):
|
||||||
|
# TODO: don't recall why "always null" here?
|
||||||
|
return 'null'
|
||||||
|
|
||||||
|
if isinstance(field.schema.typ, colander.Set):
|
||||||
|
if field.cstruct is colander.null:
|
||||||
|
return '[]'
|
||||||
|
|
||||||
|
if field.cstruct is colander.null:
|
||||||
|
return 'null'
|
||||||
|
|
||||||
|
return json.dumps(field.cstruct)
|
||||||
|
|
||||||
def messages_json(self, messages):
|
def messages_json(self, messages):
|
||||||
dump = json.dumps(messages)
|
dump = json.dumps(messages)
|
||||||
dump = dump.replace("'", ''')
|
dump = dump.replace("'", ''')
|
||||||
|
|
91
tailbone/static/js/tailbone.buefy.autocomplete.js
Normal file
91
tailbone/static/js/tailbone.buefy.autocomplete.js
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
|
||||||
|
const TailboneAutocomplete = {
|
||||||
|
|
||||||
|
template: '#tailbone-autocomplete-template',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
name: String,
|
||||||
|
serviceUrl: String,
|
||||||
|
value: String,
|
||||||
|
initialLabel: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
let selected = null
|
||||||
|
if (this.value) {
|
||||||
|
selected = {
|
||||||
|
value: this.value,
|
||||||
|
label: this.initialLabel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
data: [],
|
||||||
|
selected: selected,
|
||||||
|
isFetching: false,
|
||||||
|
autocompleteValue: this.value,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
clearSelection() {
|
||||||
|
this.selected = null
|
||||||
|
this.autocompleteValue = null
|
||||||
|
this.$nextTick(function() {
|
||||||
|
this.$refs.autocomplete.focus()
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO: should emit event for caller logic (can they cancel?)
|
||||||
|
// $('#' + oid + '-textbox').trigger('autocompletevaluecleared');
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: should we allow custom callback? or is event enough?
|
||||||
|
// function (oid) {
|
||||||
|
// $('#' + oid + '-textbox').on('autocompletevaluecleared', function() {
|
||||||
|
// ${cleared_callback}();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
selectionMade(option) {
|
||||||
|
this.selected = option
|
||||||
|
|
||||||
|
// TODO: should emit event for caller logic (can they cancel?)
|
||||||
|
// $('#' + oid + '-textbox').trigger('autocompletevalueselected',
|
||||||
|
// [ui.item.value, ui.item.label]);
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: should we allow custom callback? or is event enough?
|
||||||
|
// function (oid) {
|
||||||
|
// $('#' + oid + '-textbox').on('autocompletevalueselected', function(event, uuid, label) {
|
||||||
|
// ${selected_callback}(uuid, label);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
itemSelected(value) {
|
||||||
|
this.$emit('input', value)
|
||||||
|
},
|
||||||
|
|
||||||
|
// TODO: buefy example uses `debounce()` here and perhaps we should too?
|
||||||
|
// https://buefy.org/documentation/autocomplete
|
||||||
|
getAsyncData: function (entry) {
|
||||||
|
if (entry.length < 3) {
|
||||||
|
this.data = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.isFetching = true
|
||||||
|
this.$http.get(this.serviceUrl + '?term=' + encodeURIComponent(entry))
|
||||||
|
.then(({ data }) => {
|
||||||
|
this.data = data
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.data = []
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.isFetching = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.component('tailbone-autocomplete', TailboneAutocomplete)
|
|
@ -10,6 +10,8 @@ const OnceButton = {
|
||||||
':title="title"',
|
':title="title"',
|
||||||
':disabled="buttonDisabled"',
|
':disabled="buttonDisabled"',
|
||||||
'@click="clicked"',
|
'@click="clicked"',
|
||||||
|
'icon-pack="fas"',
|
||||||
|
':icon-left="iconLeft"',
|
||||||
'>',
|
'>',
|
||||||
'{{ buttonText }}',
|
'{{ buttonText }}',
|
||||||
'</b-button>'
|
'</b-button>'
|
||||||
|
@ -22,6 +24,7 @@ const OnceButton = {
|
||||||
href: String,
|
href: String,
|
||||||
text: String,
|
text: String,
|
||||||
title: String,
|
title: String,
|
||||||
|
iconLeft: String,
|
||||||
working: String,
|
working: String,
|
||||||
workingText: String,
|
workingText: String,
|
||||||
disabled: Boolean
|
disabled: Boolean
|
||||||
|
|
|
@ -13,3 +13,12 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
width: 18em;
|
width: 18em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field.is-horizontal .field-body {
|
||||||
|
min-width: 30em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field.is-horizontal .field-body .select,
|
||||||
|
.field.is-horizontal .field-body .select select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
## -*- coding: utf-8 -*-
|
## -*- coding: utf-8; -*-
|
||||||
|
|
||||||
## TODO: This function signature is getting out of hand...
|
## TODO: This function signature is getting out of hand...
|
||||||
<%def name="autocomplete(field_name, service_url, field_value=None, field_display=None, width='300px', select=None, selected=None, cleared=None, change_clicked=None, options={})">
|
<%def name="autocomplete(field_name, service_url, field_value=None, field_display=None, width='300px', select=None, selected=None, cleared=None, change_clicked=None, options={})">
|
||||||
<div id="${field_name}-container" class="autocomplete-container">
|
<div id="${field_name}-container" class="autocomplete-container">
|
||||||
|
@ -56,3 +57,31 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="tailbone_autocomplete_template()">
|
||||||
|
<script type="text/x-template" id="tailbone-autocomplete-template">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<b-autocomplete ref="autocomplete"
|
||||||
|
:name="name"
|
||||||
|
v-show="!selected"
|
||||||
|
v-model="autocompleteValue"
|
||||||
|
:data="data"
|
||||||
|
@typing="getAsyncData"
|
||||||
|
@select="selectionMade"
|
||||||
|
@input="itemSelected"
|
||||||
|
keep-first>
|
||||||
|
<template slot-scope="props">
|
||||||
|
{{ props.option.label }}
|
||||||
|
</template>
|
||||||
|
</b-autocomplete>
|
||||||
|
|
||||||
|
<b-button v-if="selected"
|
||||||
|
style="width: 100%; justify-content: left;"
|
||||||
|
@click="clearSelection()">
|
||||||
|
{{ selected.label }} (click to change)
|
||||||
|
</b-button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
</%def>
|
||||||
|
|
|
@ -2,10 +2,14 @@
|
||||||
css_class css_class|field.widget.css_class;
|
css_class css_class|field.widget.css_class;
|
||||||
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;
|
||||||
id="${oid}-container"
|
url url|field.widget.service_url;
|
||||||
class="autocomplete-container">
|
use_buefy use_buefy|0;"
|
||||||
|
tal:omit-tag="">
|
||||||
|
|
||||||
|
<div tal:condition="not use_buefy"
|
||||||
|
id="${oid}-container"
|
||||||
|
class="autocomplete-container">
|
||||||
<input type="hidden"
|
<input type="hidden"
|
||||||
name="${name}"
|
name="${name}"
|
||||||
id="${oid}"
|
id="${oid}"
|
||||||
|
@ -98,5 +102,16 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div tal:condition="use_buefy"
|
||||||
|
tal:define="vmodel vmodel|'field_model_' + name;"
|
||||||
|
tal:omit-tag="">
|
||||||
|
<tailbone-autocomplete name="${name}"
|
||||||
|
service-url="${url}"
|
||||||
|
v-model="${vmodel}"
|
||||||
|
initial-label="${field_display}">
|
||||||
|
</tailbone-autocomplete>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
<div class="checkbox">
|
<div tal:define="name name|field.name;
|
||||||
<input tal:define="name name|field.name;
|
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;"
|
||||||
type="checkbox"
|
tal:omit-tag="">
|
||||||
|
|
||||||
|
<div tal:condition="not use_buefy" class="checkbox">
|
||||||
|
<input type="checkbox"
|
||||||
name="${name}" value="${true_val}"
|
name="${name}" value="${true_val}"
|
||||||
id="${oid}"
|
id="${oid}"
|
||||||
tal:attributes="checked cstruct == true_val;
|
tal:attributes="checked cstruct == true_val;
|
||||||
class css_class;
|
class css_class;
|
||||||
style style;" />
|
style style;" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div tal:condition="use_buefy"
|
||||||
|
tal:define="vmodel vmodel|'field_model_' + name;">
|
||||||
|
<b-checkbox name="${name}"
|
||||||
|
v-model="${vmodel}"
|
||||||
|
native-value="${true_val}">
|
||||||
|
{{ ${vmodel} }}
|
||||||
|
</b-checkbox>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
60
tailbone/templates/deform/checked_password.pt
Normal file
60
tailbone/templates/deform/checked_password.pt
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<div i18n:domain="deform" tal:omit-tag=""
|
||||||
|
tal:define="oid oid|field.oid;
|
||||||
|
name name|field.name;
|
||||||
|
css_class css_class|field.widget.css_class;
|
||||||
|
style style|field.widget.style;
|
||||||
|
use_buefy use_buefy|0;">
|
||||||
|
|
||||||
|
<div tal:condition="not use_buefy" tal:omit-tag="">
|
||||||
|
${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()}
|
||||||
|
<b-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">
|
||||||
|
</b-input>
|
||||||
|
<b-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">
|
||||||
|
</b-input>
|
||||||
|
${field.end_mapping()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
|
@ -58,12 +58,14 @@
|
||||||
|
|
||||||
<div tal:condition="use_buefy"
|
<div tal:condition="use_buefy"
|
||||||
tal:define="vmodel vmodel|'field_model_' + name;"
|
tal:define="vmodel vmodel|'field_model_' + name;"
|
||||||
tal:omit-tag="">
|
>
|
||||||
|
<input type="hidden" name="__start__" value="${name}:sequence"
|
||||||
|
tal:condition="multiple" />
|
||||||
<b-select tal:attributes="name name;
|
<b-select tal:attributes="name name;
|
||||||
id oid;
|
id oid;
|
||||||
placeholder '(please choose)';
|
placeholder '(please choose)';
|
||||||
class string: form-control ${css_class or ''};
|
class string: form-control ${css_class or ''};
|
||||||
multiple multiple;
|
:multiple str(multiple).lower();
|
||||||
size size;
|
size size;
|
||||||
style style;
|
style style;
|
||||||
v-model vmodel;
|
v-model vmodel;
|
||||||
|
@ -88,6 +90,8 @@
|
||||||
</tal:loop>
|
</tal:loop>
|
||||||
|
|
||||||
</b-select>
|
</b-select>
|
||||||
|
<input type="hidden" name="__end__" value="${name}:sequence"
|
||||||
|
tal:condition="multiple" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
27
tailbone/templates/deform/textarea.pt
Normal file
27
tailbone/templates/deform/textarea.pt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<div tal:define="rows rows|field.widget.rows;
|
||||||
|
cols cols|field.widget.cols;
|
||||||
|
css_class css_class|field.widget.css_class;
|
||||||
|
oid oid|field.oid;
|
||||||
|
name name|field.name;
|
||||||
|
style style|field.widget.style;
|
||||||
|
use_buefy use_buefy|0;"
|
||||||
|
tal:omit-tag="">
|
||||||
|
|
||||||
|
<div tal:condition="not use_buefy" tal:omit-tag="">
|
||||||
|
<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"
|
||||||
|
name="${name}"
|
||||||
|
v-model="${vmodel}">
|
||||||
|
</b-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
32
tailbone/templates/deform/textinput.pt
Normal file
32
tailbone/templates/deform/textinput.pt
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<span tal:define="name name|field.name;
|
||||||
|
css_class css_class|field.widget.css_class;
|
||||||
|
oid oid|field.oid;
|
||||||
|
mask mask|field.widget.mask;
|
||||||
|
mask_placeholder mask_placeholder|field.widget.mask_placeholder;
|
||||||
|
style style|field.widget.style;
|
||||||
|
use_buefy use_buefy|0;"
|
||||||
|
tal:omit-tag="">
|
||||||
|
<div tal:condition="not use_buefy" tal:omit-tag="">
|
||||||
|
<input type="text" name="${name}" value="${cstruct}"
|
||||||
|
tal:attributes="class string: form-control ${css_class or ''};
|
||||||
|
style style;
|
||||||
|
attributes|field.widget.attributes|{};"
|
||||||
|
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="">
|
||||||
|
<b-input name="${name}"
|
||||||
|
v-model="${vmodel}">
|
||||||
|
</b-input>
|
||||||
|
</div>
|
||||||
|
</span>
|
|
@ -11,7 +11,38 @@
|
||||||
${form.render(buttons=capture(self.render_form_buttons))|n}
|
${form.render(buttons=capture(self.render_form_buttons))|n}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_buefy_form()">
|
||||||
|
<div class="form">
|
||||||
|
<tailbone-form></tailbone-form>
|
||||||
|
</div>
|
||||||
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form_complete()">
|
<%def name="render_form_complete()">
|
||||||
|
% if use_buefy:
|
||||||
|
${self.render_form()}
|
||||||
|
<script type="text/x-template" id="form-page-template">
|
||||||
|
<div style="display: flex; justify-content: space-between;">
|
||||||
|
|
||||||
|
<div class="form-wrapper">
|
||||||
|
${self.render_buefy_form()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
</script>
|
||||||
|
<div id="form-page-app">
|
||||||
|
<form-page></form-page>
|
||||||
|
</div>
|
||||||
|
% else:
|
||||||
<div style="display: flex; justify-content: space-between;">
|
<div style="display: flex; justify-content: space-between;">
|
||||||
|
|
||||||
<div class="form-wrapper">
|
<div class="form-wrapper">
|
||||||
|
@ -29,6 +60,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="modify_tailbone_form()">
|
<%def name="modify_tailbone_form()">
|
||||||
|
@ -43,8 +75,14 @@
|
||||||
|
|
||||||
Vue.component('tailbone-form', TailboneForm)
|
Vue.component('tailbone-form', TailboneForm)
|
||||||
|
|
||||||
|
const FormPage = {
|
||||||
|
template: '#form-page-template'
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.component('form-page', FormPage)
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
el: '#tailbone-form-app'
|
el: '#form-page-app'
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -53,6 +91,6 @@
|
||||||
|
|
||||||
${self.render_form_complete()}
|
${self.render_form_complete()}
|
||||||
|
|
||||||
% if form.use_buefy:
|
% if use_buefy:
|
||||||
${self.make_tailbone_form_app()}
|
${self.make_tailbone_form_app()}
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -91,21 +91,10 @@
|
||||||
% for field in form.fields:
|
% for field in form.fields:
|
||||||
% if field in dform:
|
% if field in dform:
|
||||||
<% field = dform[field] %>
|
<% field = dform[field] %>
|
||||||
% if isinstance(field.schema.typ, colander.Date):
|
field_model_${field.name}: ${form.get_vuejs_model_value(field)|n},
|
||||||
field_model_${field.name}: null,
|
|
||||||
% elif isinstance(field.schema.typ, deform.FileData):
|
|
||||||
field_model_${field.name}: null,
|
|
||||||
% else:
|
|
||||||
field_model_${field.name}: ${'null' if field.cstruct is colander.null else json.dumps(field.cstruct)|n},
|
|
||||||
% endif
|
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div id="tailbone-form-app">
|
|
||||||
<tailbone-form></tailbone-form>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -20,16 +20,28 @@
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_form()">
|
<%def name="render_buefy_form()">
|
||||||
<br />
|
<br />
|
||||||
|
% if use_buefy:
|
||||||
|
<b-notification type="is-danger" :closable="false">
|
||||||
|
You are about to delete the following ${model_title} and all associated data:
|
||||||
|
</b-notification>
|
||||||
|
% else:
|
||||||
<p>You are about to delete the following ${model_title} and all associated data:</p>
|
<p>You are about to delete the following ${model_title} and all associated data:</p>
|
||||||
|
% endif
|
||||||
|
|
||||||
${parent.render_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">
|
||||||
|
Are you sure about this?
|
||||||
|
</b-notification>
|
||||||
|
% else:
|
||||||
<p>Are you sure about this?</p>
|
<p>Are you sure about this?</p>
|
||||||
|
% endif
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
${h.form(request.current_route_url(), class_=None if form.use_buefy else 'autodisable')}
|
${h.form(request.current_route_url(), class_=None if form.use_buefy else 'autodisable')}
|
||||||
|
@ -39,15 +51,13 @@
|
||||||
<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>
|
||||||
% else:
|
<once-button type="is-primary is-danger"
|
||||||
<a class="button" href="${form.cancel_url}">Whoops, nevermind...</a>
|
native-type="submit"
|
||||||
% endif
|
|
||||||
% if form.use_buefy:
|
|
||||||
<once-button type="is-primary" native-type="submit"
|
|
||||||
text="Yes, please DELETE this data forever!">
|
text="Yes, please DELETE this data forever!">
|
||||||
</once-button>
|
</once-button>
|
||||||
% else:
|
% else:
|
||||||
${h.submit('submit', "Yes, please DELETE this data forever!", class_='button is-primary')}
|
<a class="button" href="${form.cancel_url}">Whoops, nevermind...</a>
|
||||||
|
${h.submit('submit', "Yes, please DELETE this data forever!", class_='button is-primary')}
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
|
|
|
@ -141,13 +141,12 @@
|
||||||
<input type="hidden"
|
<input type="hidden"
|
||||||
name="uuids"
|
name="uuids"
|
||||||
:value="checkedRowUUIDs()" />
|
:value="checkedRowUUIDs()" />
|
||||||
<b-button type="is-primary"
|
<once-button type="is-primary"
|
||||||
native-type="submit"
|
native-type="submit"
|
||||||
icon-pack="fas"
|
icon-left="object-ungroup"
|
||||||
icon-left="object-ungroup"
|
:disabled="checkedRows.length != 2"
|
||||||
:disabled="checkedRows.length != 2">
|
text="Merge 2 ${model_title_plural}">
|
||||||
Merge 2 ${model_title_plural}
|
</once-button>
|
||||||
</b-button>
|
|
||||||
% else:
|
% else:
|
||||||
${h.hidden('uuids')}
|
${h.hidden('uuids')}
|
||||||
<button type="submit" class="button">Merge 2 ${model_title_plural}</button>
|
<button type="submit" class="button">Merge 2 ${model_title_plural}</button>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%namespace file="/grids/nav.mako" import="grid_index_nav" />
|
<%namespace file="/grids/nav.mako" import="grid_index_nav" />
|
||||||
<%namespace file="/feedback_dialog_buefy.mako" import="feedback_dialog" />
|
<%namespace file="/feedback_dialog_buefy.mako" import="feedback_dialog" />
|
||||||
|
<%namespace file="/autocomplete.mako" import="tailbone_autocomplete_template" />
|
||||||
<%namespace name="base_meta" file="/base_meta.mako" />
|
<%namespace name="base_meta" file="/base_meta.mako" />
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
@ -30,6 +31,11 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
## TODO: should move template to JS, then can postpone the JS
|
||||||
|
${tailbone_autocomplete_template()}
|
||||||
|
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.autocomplete.js') + '?ver={}'.format(tailbone.__version__))}
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
|
||||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||||
|
|
Loading…
Reference in a new issue