Refactory Buefy templates to use WholePage and ThisPage components

plus add `GridFilter.set_choices()` method
This commit is contained in:
Lance Edgar 2019-08-03 16:57:13 -05:00
parent c64fca852c
commit 1bb0330ab5
36 changed files with 806 additions and 613 deletions

View file

@ -1003,7 +1003,10 @@ class Grid(object):
choices = [] choices = []
choice_labels = {} choice_labels = {}
if self.enums and filtr.key in self.enums: if filtr.choices:
choices = list(filtr.choices)
choices_labels = dict(filtr.choices)
elif self.enums and filtr.key in self.enums:
choices = list(self.enums[filtr.key]) choices = list(self.enums[filtr.key])
choice_labels = self.enums[filtr.key] choice_labels = self.enums[filtr.key]

View file

@ -149,6 +149,7 @@ class GridFilter(object):
value_renderer_factory = DefaultValueRenderer value_renderer_factory = DefaultValueRenderer
data_type = 'string' # default, but will be set from value renderer data_type = 'string' # default, but will be set from value renderer
choices = {}
def __init__(self, key, label=None, verbs=None, value_enum=None, value_renderer=None, def __init__(self, key, label=None, verbs=None, value_enum=None, value_renderer=None,
default_active=False, default_verb=None, default_value=None, default_active=False, default_verb=None, default_value=None,
@ -187,6 +188,27 @@ class GridFilter(object):
return verbs return verbs
return ['equal', 'not_equal', 'is_null', 'is_not_null', 'is_any'] return ['equal', 'not_equal', 'is_null', 'is_not_null', 'is_any']
def set_choices(self, choices):
"""
Set the value choices for the filter, post-construction. Note that
this also will set the value renderer to one which supports choices.
"""
# first must normalize choices
if isinstance(choices, OrderedDict):
normalized = choices
elif isinstance(choices, dict):
normalized = OrderedDict([
(key, choices[value])
for key in sorted(choices)])
elif isinstance(choices, list):
normalized = OrderedDict([
(key, key)
for key in choices])
# store normalized choices, and set renderer
self.choices = normalized
self.set_value_renderer(ChoiceValueRenderer(self.choices))
def set_value_renderer(self, renderer): def set_value_renderer(self, renderer):
""" """
Set the value renderer for the filter, post-construction. Set the value renderer for the filter, post-construction.

View file

@ -174,9 +174,3 @@ let TailboneGrid = {
} }
} }
} }
let GridPage = {
template: '#grid-page-template',
methods: {}
}

View file

@ -1,14 +1,19 @@
## -*- coding: utf-8 -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%namespace name="base_meta" file="/base_meta.mako" /> <%namespace name="base_meta" file="/base_meta.mako" />
<%def name="title()">About ${base_meta.app_title()}</%def> <%def name="title()">About ${base_meta.app_title()}</%def>
<h2>${project_title} ${project_version}</h2> <%def name="page_content()">
<h2>${project_title} ${project_version}</h2>
% for name, version in packages.items(): % for name, version in packages.items():
<h3>${name} ${version}</h3> <h3>${name} ${version}</h3>
% endfor % endfor
<br /> <br />
<p>Please see <a href="https://rattailproject.org/">rattailproject.org</a> for more info.</p> <p>Please see <a href="https://rattailproject.org/">rattailproject.org</a> for more info.</p>
</%def>
${parent.body()}

View file

@ -1,5 +1,5 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%def name="title()">App Settings</%def> <%def name="title()">App Settings</%def>
@ -33,8 +33,18 @@
% endif % endif
</%def> </%def>
<%def name="context_menu_items()">
% if request.has_perm('settings.list'):
<li>${h.link_to("View Raw Settings", url('settings'))}</li>
% endif
</%def>
% if use_buefy: <%def name="page_content()">
<app-settings :groups="groups" :showing-group="showingGroup"></app-settings>
</%def>
<%def name="render_this_page_template()">
${parent.render_this_page_template()}
<script type="text/x-template" id="app-settings-template"> <script type="text/x-template" id="app-settings-template">
<div class="form"> <div class="form">
@ -139,11 +149,20 @@
${h.end_form()} ${h.end_form()}
</div> </div>
</script> </script>
</%def>
<div id="app-settings-app"> <%def name="modify_this_page_vars()">
<app-settings :groups="groups" :showing-group="showingGroup"></app-settings> ${parent.modify_this_page_vars()}
</div> <script type="text/javascript">
ThisPageData.groups = ${json.dumps(buefy_data)|n}
ThisPageData.showingGroup = ${json.dumps(current_group or '')|n}
</script>
</%def>
<%def name="make_this_page_component()">
${parent.make_this_page_component()}
<script type="text/javascript"> <script type="text/javascript">
Vue.component('app-settings', { Vue.component('app-settings', {
@ -166,17 +185,12 @@
} }
}) })
new Vue({
el: '#app-settings-app',
data() {
return {
groups: ${json.dumps(buefy_data)|n},
showingGroup: ${json.dumps(current_group or '')|n}
}
}
})
</script> </script>
</%def>
% if use_buefy:
${parent.body()}
% else: % else:
## legacy / not buefy ## legacy / not buefy

View file

@ -107,19 +107,15 @@
% endif % endif
</%def> </%def>
<%def name="modify_tailbone_grid()"> <%def name="modify_this_page_vars()">
${parent.modify_tailbone_grid()} ${parent.modify_this_page_vars()}
% if master.results_executable and request.has_perm('{}.execute_multiple'.format(permission_prefix)): % if master.results_executable and request.has_perm('{}.execute_multiple'.format(permission_prefix)):
<script type="text/javascript"> <script type="text/javascript">
TailboneForm.data = function() { return TailboneFormData }
TailboneForm.methods.submit = function() { TailboneForm.methods.submit = function() {
this.$refs.actualForm.submit() this.$refs.actualForm.submit()
} }
Vue.component('tailbone-form', TailboneForm)
TailboneGridData.hasExecutionOptions = ${json.dumps(master.has_execution_options(batch))|n} TailboneGridData.hasExecutionOptions = ${json.dumps(master.has_execution_options(batch))|n}
TailboneGridData.showExecutionOptions = false TailboneGridData.showExecutionOptions = false
@ -151,12 +147,26 @@
% endif % endif
</%def> </%def>
<%def name="make_this_page_component()">
${parent.make_this_page_component()}
% if master.results_executable and request.has_perm('{}.execute_multiple'.format(permission_prefix)):
<script type="text/javascript">
% if use_buefy: TailboneForm.data = function() { return TailboneFormData }
Vue.component('tailbone-form', TailboneForm)
</script>
% endif
</%def>
<%def name="render_this_page_template()">
${parent.render_this_page_template()}
% if master.results_executable and request.has_perm('{}.execute_multiple'.format(permission_prefix)): % if master.results_executable and request.has_perm('{}.execute_multiple'.format(permission_prefix)):
${execute_form.render_deform(form_kwargs={'ref': 'actualForm'}, buttons=False)|n} ${execute_form.render_deform(form_kwargs={'ref': 'actualForm'}, buttons=False)|n}
% endif % endif
% endif </%def>
${parent.body()} ${parent.body()}

View file

@ -187,16 +187,16 @@
% endif % endif
</%def> </%def>
<%def name="render_this_page_buefy()"> <%def name="render_this_page_template()">
${parent.render_this_page_template()}
% if use_buefy and master.handler.executable(batch) and request.has_perm('{}.execute'.format(permission_prefix)): % if use_buefy and master.handler.executable(batch) and request.has_perm('{}.execute'.format(permission_prefix)):
## TODO: stop using |n filter ## TODO: stop using |n filter
${execute_form.render_deform(buttons=capture(execute_submit_button), form_kwargs={'@submit': 'submitExecuteForm'})|n} ${execute_form.render_deform(buttons=capture(execute_submit_button), form_kwargs={'@submit': 'submitExecuteForm'})|n}
% endif % endif
${parent.render_this_page_buefy()}
</%def> </%def>
<%def name="modify_this_page()"> <%def name="modify_this_page_vars()">
${parent.modify_this_page()} ${parent.modify_this_page_vars()}
% if not batch.executed and request.has_perm('{}.execute'.format(permission_prefix)): % if not batch.executed and request.has_perm('{}.execute'.format(permission_prefix)):
<script type="text/javascript"> <script type="text/javascript">
@ -216,8 +216,8 @@
% endif % endif
</%def> </%def>
<%def name="finalize_page_components()"> <%def name="finalize_this_page_vars()">
${parent.finalize_page_components()} ${parent.finalize_this_page_vars()}
% if not batch.executed and request.has_perm('{}.execute'.format(permission_prefix)): % if not batch.executed and request.has_perm('{}.execute'.format(permission_prefix)):
<script type="text/javascript"> <script type="text/javascript">

View file

@ -1,8 +1,13 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%def name="title()">Change Password</%def> <%def name="title()">Change Password</%def>
<div class="form"> <%def name="page_content()">
<div class="form">
${form.render_deform()|n} ${form.render_deform()|n}
</div> </div>
</%def>
${parent.body()}

View file

@ -42,8 +42,8 @@
</%def> </%def>
<%def name="modify_tailbone_grid()"> <%def name="modify_this_page_vars()">
${parent.modify_tailbone_grid()} ${parent.modify_this_page_vars()}
<script type="text/javascript"> <script type="text/javascript">
% if request.has_perm('datasync.restart'): % if request.has_perm('datasync.restart'):

View file

@ -1,13 +1,18 @@
## -*- coding: utf-8 -*- ## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" /> <%inherit file="/master/view.mako" />
${parent.body()} <%def name="page_content()">
${parent.page_content()}
<h2>Employees</h2> <h2>Employees</h2>
% if employees: % if employees:
<p>The following employees are assigned to this department:</p> <p>The following employees are assigned to this department:</p>
${employees.render_grid()|n} ${employees.render_grid()|n}
% else: % else:
<p>No employees are assigned to this department.</p> <p>No employees are assigned to this department.</p>
% endif % endif
</%def>
${parent.body()}

View file

@ -1,16 +1,10 @@
## -*- coding: utf-8 -*- ## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" /> <%inherit file="/master/view.mako" />
<%def name="head_tags()"> ## TODO: this page still uses jQuery but should use Vue.js
${parent.head_tags()}
<style type="text/css"> <%def name="extra_javascript()">
#message { ${parent.extra_javascript()}
border: 1px solid #000000;
height: 400px;
overflow: auto;
padding: 4px;
}
</style>
<script type="text/javascript"> <script type="text/javascript">
function autosize_message(scrolldown) { function autosize_message(scrolldown) {
@ -34,6 +28,18 @@
</script> </script>
</%def> </%def>
<%def name="extra_styles()">
${parent.extra_styles()}
<style type="text/css">
#message {
border: 1px solid #000000;
height: 400px;
overflow: auto;
padding: 4px;
}
</style>
</%def>
<%def name="context_menu_items()"> <%def name="context_menu_items()">
${parent.context_menu_items()} ${parent.context_menu_items()}
% if not bounce.processed and request.has_perm('emailbounces.process'): % if not bounce.processed and request.has_perm('emailbounces.process'):
@ -43,8 +49,12 @@
% endif % endif
</%def> </%def>
${parent.body()} <%def name="page_content()">
${parent.page_content()}
<pre id="message">
${message}
</pre>
</%def>
<pre id="message">
${message} ${parent.body()}
</pre>

View file

@ -45,15 +45,15 @@
</div> </div>
</%def> </%def>
<%def name="render_this_page_buefy()"> <%def name="render_this_page_template()">
% if form is not Underined: % if form is not Underined:
${self.render_form()} ${self.render_form()}
% endif % endif
${parent.render_this_page_buefy()} ${parent.render_this_page_template()}
</%def> </%def>
<%def name="finalize_page_components()"> <%def name="finalize_this_page_vars()">
${parent.finalize_page_components()} ${parent.finalize_this_page_vars()}
% if form is not Undefined: % if form is not Undefined:
<script type="text/javascript"> <script type="text/javascript">

View file

@ -1,5 +1,5 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%namespace name="base_meta" file="/base_meta.mako" /> <%namespace name="base_meta" file="/base_meta.mako" />
<%def name="title()">Home</%def> <%def name="title()">Home</%def>
@ -16,7 +16,12 @@
</style> </style>
</%def> </%def>
<div class="logo"> <%def name="page_content()">
<div class="logo">
${h.image(image_url, "{} logo".format(capture(base_meta.app_title)), id='logo', width=500)} ${h.image(image_url, "{} logo".format(capture(base_meta.app_title)), id='logo', width=500)}
<h1>Welcome to ${base_meta.app_title()}</h1> <h1>Welcome to ${base_meta.app_title()}</h1>
</div> </div>
</%def>
${parent.body()}

View file

@ -24,10 +24,11 @@
% endif % endif
</%def> </%def>
${parent.body()} <%def name="page_content()">
${parent.page_content()}
<% printer = instance.get_printer(request.rattail_config) %> <% printer = instance.get_printer(request.rattail_config) %>
% if printer and printer.required_settings: % if printer and printer.required_settings:
<h2>Printer Settings</h2> <h2>Printer Settings</h2>
<div class="form"> <div class="form">
@ -39,4 +40,8 @@ ${parent.body()}
% endfor % endfor
</div> </div>
% endif % endif
</%def>
${parent.body()}

View file

@ -1,5 +1,5 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%namespace name="base_meta" file="/base_meta.mako" /> <%namespace name="base_meta" file="/base_meta.mako" />
<%def name="title()">Login</%def> <%def name="title()">Login</%def>
@ -24,12 +24,17 @@
</div> </div>
</%def> </%def>
${self.logo()} <%def name="page_content()">
${self.logo()}
${self.login_form()} ${self.login_form()}
% if request.rattail_config.demo(): % if request.rattail_config.demo():
<p class="tips"> <p class="tips">
Login with <strong>chuck / admin</strong> for full demo access Login with <strong>chuck / admin</strong> for full demo access
</p> </p>
% endif % endif
</%def>
${parent.body()}

View file

@ -52,8 +52,8 @@
${h.end_form()} ${h.end_form()}
</%def> </%def>
<%def name="modify_this_page()"> <%def name="modify_this_page_vars()">
${parent.modify_this_page()} ${parent.modify_this_page_vars()}
<script type="text/javascript"> <script type="text/javascript">
TailboneFormData.formSubmitting = false TailboneFormData.formSubmitting = false

View file

@ -68,8 +68,8 @@
${h.end_form()} ${h.end_form()}
</%def> </%def>
<%def name="modify_this_page()"> <%def name="modify_this_page_vars()">
${parent.modify_this_page()} ${parent.modify_this_page_vars()}
<script type="text/javascript"> <script type="text/javascript">
TailboneFormData.formSubmitting = false TailboneFormData.formSubmitting = false

View file

@ -26,8 +26,8 @@
% endif % endif
</%def> </%def>
<%def name="modify_this_page()"> <%def name="modify_this_page_vars()">
${parent.modify_this_page()} ${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':
<script type="text/javascript"> <script type="text/javascript">

View file

@ -6,7 +6,7 @@
## include a "tools" section, just above the grid on the right. ## include a "tools" section, just above the grid on the right.
## ##
## ############################################################################## ## ##############################################################################
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%def name="title()">${index_title}</%def> <%def name="title()">${index_title}</%def>
@ -215,57 +215,7 @@
</%def> </%def>
<%def name="modify_tailbone_grid()"> <%def name="page_content()">
<script type="text/javascript">
% if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)):
TailboneGridData.mergeFormButtonText = "Merge 2 ${model_title_plural}"
TailboneGridData.mergeFormSubmitting = false
TailboneGrid.methods.submitMergeForm = function() {
this.mergeFormSubmitting = true
this.mergeFormButtonText = "Working, please wait..."
}
% endif
</script>
</%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)
% if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
GridPage.methods.deleteObject = function(url) {
if (confirm("Are you sure you wish to delete this ${model_title}?")) {
let form = this.$refs.deleteObjectForm
form.action = url
form.submit()
}
}
% endif
Vue.component('grid-page', GridPage)
new Vue({
el: '#grid-page-app'
})
</script>
</%def>
% if use_buefy:
## TODO: stop using |n filter
${grid.render_buefy(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
<script type="text/x-template" id="grid-page-template">
<div>
<tailbone-grid <tailbone-grid
% if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple': % if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
@deleteActionClicked="deleteObject" @deleteActionClicked="deleteObject"
@ -277,14 +227,56 @@
${h.csrf_token(request)} ${h.csrf_token(request)}
${h.end_form()} ${h.end_form()}
% endif % endif
</div> </%def>
<%def name="modify_this_page_vars()">
${parent.modify_this_page_vars()}
<script type="text/javascript">
% if master.mergeable and request.has_perm('{}.merge'.format(permission_prefix)):
TailboneGridData.mergeFormButtonText = "Merge 2 ${model_title_plural}"
TailboneGridData.mergeFormSubmitting = false
TailboneGrid.methods.submitMergeForm = function() {
this.mergeFormSubmitting = true
this.mergeFormButtonText = "Working, please wait..."
}
% endif
% if master.deletable and request.has_perm('{}.delete'.format(permission_prefix)) and master.delete_confirm == 'simple':
ThisPage.methods.deleteObject = function(url) {
if (confirm("Are you sure you wish to delete this ${model_title}?")) {
let form = this.$refs.deleteObjectForm
form.action = url
form.submit()
}
}
% endif
</script> </script>
</%def>
<div id="grid-page-app"> <%def name="make_this_page_component()">
<grid-page></grid-page> ${parent.make_this_page_component()}
</div> <script type="text/javascript">
${self.make_tailbone_grid_app()} TailboneGrid.data = function() { return TailboneGridData }
Vue.component('tailbone-grid', TailboneGrid)
</script>
</%def>
<%def name="render_this_page()">
${self.page_content()}
</%def>
<%def name="render_this_page_template()">
${parent.render_this_page_template()}
## TODO: stop using |n filter
${grid.render_buefy(tools=capture(self.grid_tools).strip(), context_menu=capture(self.context_menu_items).strip())|n}
</%def>
% if use_buefy:
${parent.body()}
% else: % else:
## no buefy, so do the traditional thing ## no buefy, so do the traditional thing

View file

@ -154,9 +154,10 @@ ${h.end_form()}
% endif % endif
</%def> </%def>
<%def name="render_this_page_template()">
${parent.render_this_page_template()}
% if use_buefy: <script type="text/x-template" id="merge-buttons-template">
<script type="text/x-template" id="merge-buttons-template">
<div class="level" style="margin-top: 2em;"> <div class="level" style="margin-top: 2em;">
<div class="level-left"> <div class="level-left">
@ -194,9 +195,12 @@ ${h.end_form()}
</div> </div>
</div> </div>
</script> </script>
</%def>
<script type="text/javascript"> <%def name="make_this_page_component()">
${parent.make_this_page_component()}
<script type="text/javascript">
const MergeButtons = { const MergeButtons = {
template: '#merge-buttons-template', template: '#merge-buttons-template',
@ -222,7 +226,8 @@ ${h.end_form()}
Vue.component('merge-buttons', MergeButtons) Vue.component('merge-buttons', MergeButtons)
</script> </script>
% endif </%def>
${parent.body()} ${parent.body()}

View file

@ -4,7 +4,9 @@
## Default master 'versions' template, for showing an object's version history. ## Default master 'versions' template, for showing an object's version history.
## ##
## ############################################################################## ## ##############################################################################
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
## TODO: this page still uses old-style grid but should use Buefy grid
<%def name="title()">${model_title_plural} » ${instance_title} » history</%def> <%def name="title()">${model_title_plural} » ${instance_title} » history</%def>
@ -21,4 +23,9 @@
History for ${instance_title} History for ${instance_title}
</%def> </%def>
${grid.render_complete()|n} <%def name="page_content()">
${grid.render_complete()|n}
</%def>
${parent.body()}

View file

@ -93,15 +93,15 @@
% endif % endif
</%def> </%def>
<%def name="render_this_page_buefy()"> <%def name="render_this_page_template()">
% if master.has_rows: % if master.has_rows:
## 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}
% endif % endif
${parent.render_this_page_buefy()} ${parent.render_this_page_template()}
</%def> </%def>
<%def name="make_this_page_app()"> <%def name="make_this_page_component()">
<script type="text/javascript"> <script type="text/javascript">
TailboneGrid.data = function() { return TailboneGridData } TailboneGrid.data = function() { return TailboneGridData }
@ -109,7 +109,7 @@
Vue.component('tailbone-grid', TailboneGrid) Vue.component('tailbone-grid', TailboneGrid)
</script> </script>
${parent.make_this_page_app()} ${parent.make_this_page_component()}
</%def> </%def>

View file

@ -1,8 +1,9 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%def name="title()">${instance_title_normal} @ ver ${transaction.id}</%def> <%def name="title()">${instance_title_normal} @ ver ${transaction.id}</%def>
<%def name="page_content()">
## TODO: this was basically copied from Revel diff template..need to abstract ## TODO: this was basically copied from Revel diff template..need to abstract
<div class="form-wrapper"> <div class="form-wrapper">
@ -97,3 +98,7 @@
% endif % endif
% endfor % endfor
</%def>
${parent.body()}

View file

@ -1,4 +1,4 @@
## -*- coding: utf-8 -*- ## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" /> <%inherit file="/master/view.mako" />
<%def name="extra_javascript()"> <%def name="extra_javascript()">
@ -87,12 +87,17 @@
${instance.body} ${instance.body}
</%def> </%def>
${parent.body()} <%def name="page_content()">
${parent.page_content()}
${self.message_tools()} ${self.message_tools()}
<div class="message-body"> <div class="message-body">
${self.message_body()} ${self.message_body()}
</div> </div>
${self.message_tools()} ${self.message_tools()}
</%def>
${parent.body()}

View file

@ -6,9 +6,9 @@
<%def name="page_content()"></%def> <%def name="page_content()"></%def>
<%def name="render_this_page()"> <%def name="render_this_page()">
<div style="display: flex; justify-content: space-between;"> <div style="display: flex;">
<div class="this-page-content"> <div class="this-page-content" style="flex-grow: 1;">
${self.page_content()} ${self.page_content()}
</div> </div>
@ -19,23 +19,15 @@
</div> </div>
</%def> </%def>
<%def name="render_this_page_buefy()"> <%def name="render_this_page_template()">
<script type="text/x-template" id="this-page-template"> <script type="text/x-template" id="this-page-template">
<div> <div>
${self.render_this_page()} ${self.render_this_page()}
</div> </div>
</script> </script>
<div id="this-page-app">
<this-page></this-page>
</div>
</%def> </%def>
<%def name="modify_this_page()"> <%def name="declare_this_page_vars()">
## NOTE: if you override this, must use <script> tags
</%def>
<%def name="declare_page_vars()">
<script type="text/javascript"> <script type="text/javascript">
let ThisPage = { let ThisPage = {
@ -48,31 +40,32 @@
</script> </script>
</%def> </%def>
<%def name="finalize_page_components()"> <%def name="modify_this_page_vars()">
## NOTE: if you override this, must use <script> tags ## NOTE: if you override this, must use <script> tags
</%def> </%def>
<%def name="make_this_page_app()"> <%def name="finalize_this_page_vars()">
${self.declare_page_vars()} ## NOTE: if you override this, must use <script> tags
${self.modify_this_page()} </%def>
${self.finalize_page_components()}
<%def name="make_this_page_component()">
${self.declare_this_page_vars()}
${self.modify_this_page_vars()}
${self.finalize_this_page_vars()}
<script type="text/javascript"> <script type="text/javascript">
ThisPage.data = function() { return ThisPageData } ThisPage.data = function() { return ThisPageData }
Vue.component('this-page', ThisPage) Vue.component('this-page', ThisPage)
new Vue({
el: '#this-page-app'
})
</script> </script>
</%def> </%def>
% if use_buefy: % if use_buefy:
${self.render_this_page_buefy()} ${self.render_this_page_template()}
${self.make_this_page_app()} ${self.make_this_page_component()}
% else: % else:
${self.render_this_page()} ${self.render_this_page()}
% endif % endif

View file

@ -4,7 +4,7 @@
<%def name="extra_javascript()"> <%def name="extra_javascript()">
${parent.extra_javascript()} ${parent.extra_javascript()}
% if not instance.users and request.has_perm('users.create'): % if not use_buefy and not instance.users and request.has_perm('users.create'):
<script type="text/javascript"> <script type="text/javascript">
## TODO: should do this differently for Buefy themes ## TODO: should do this differently for Buefy themes
$(function() { $(function() {
@ -26,12 +26,43 @@
${view_profiles_helper([instance])} ${view_profiles_helper([instance])}
</%def> </%def>
${parent.body()} <%def name="render_buefy_form()">
<div class="form">
<tailbone-form v-on:make-user="makeUser"></tailbone-form>
</div>
</%def>
## TODO: should do this differently for Buefy themes <%def name="modify_this_page_vars()">
% if not instance.users and request.has_perm('users.create'): ${parent.modify_this_page_vars()}
<script type="text/javascript">
TailboneForm.methods.clickMakeUser = function(event) {
this.$emit('make-user')
}
ThisPage.methods.makeUser = function(event) {
if (confirm("Really make a user account for this person?")) {
this.$refs.makeUserForm.submit()
}
}
</script>
</%def>
<%def name="page_content()">
${parent.page_content()}
% if not instance.users and request.has_perm('users.create'):
% if use_buefy:
${h.form(url('people.make_user'), ref='makeUserForm')}
% else:
${h.form(url('people.make_user'), name='make-user-form')} ${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()}
% endif % endif
</%def>
${parent.body()}

View file

@ -1,5 +1,5 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%def name="title()">Find ${model_title_plural} by Permission</%def> <%def name="title()">Find ${model_title_plural} by Permission</%def>
@ -46,40 +46,39 @@
% endif % endif
</%def> </%def>
<%def name="page_content()">
% if use_buefy:
<find-principals :permission-groups="permissionGroups"
:sorted-groups="sortedGroups">
</find-principals>
% else:
## not buefy
${h.form(request.current_route_url(), id='find-by-perm-form')}
${h.csrf_token(request)}
% if not use_buefy: <div class="form">
${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_group')}
${self.wtfield(form, 'permission')} ${self.wtfield(form, 'permission')}
<div class="buttons"> <div class="buttons">
${h.submit('submit', "Find {}".format(model_title_plural))} ${h.submit('submit', "Find {}".format(model_title_plural))}
</div> </div>
</div> </div>
${h.end_form()} ${h.end_form()}
% if principals is not None: % if principals is not None:
<div class="grid half"> <div class="grid half">
<br /> <br />
<h2>${model_title_plural} with that permission (${len(principals)} total):</h2> <h2>${model_title_plural} with that permission (${len(principals)} total):</h2>
${self.principal_table()} ${self.principal_table()}
</div> </div>
% endif % endif
% endif
</%def>
<%def name="render_this_page_template()">
% else: ${parent.render_this_page_template()}
## use_buefy! <script type="text/x-template" id="find-principals-template">
<div id="find-principals-app">
<find-principals :permission-groups="permissionGroups"
:sorted-groups="sortedGroups">
</find-principals>
</div>
<script type="text/x-template" id="find-principals-template">
<div class="app-wrapper"> <div class="app-wrapper">
${h.form(request.current_route_url(), **{'@submit': 'submitForm'})} ${h.form(request.current_route_url(), **{'@submit': 'submitForm'})}
@ -128,15 +127,28 @@ ${h.end_form()}
% if principals is not None: % if principals is not None:
<div class="grid half"> <div class="grid half">
<br /> <br />
<h2>${model_title_plural} with that permission (${len(principals)} total):</h2> <h2>Found ${len(principals)} ${model_title_plural} with permission: ${selected_permission}</h2>
${self.principal_table()} ${self.principal_table()}
</div> </div>
% endif % endif
</div><!-- app-wrapper --> </div><!-- app-wrapper -->
</script> </script>
</%def>
<script type="text/javascript"> <%def name="modify_this_page_vars()">
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPageData.permissionGroups = ${json.dumps(buefy_perms)|n}
ThisPageData.sortedGroups = ${json.dumps(buefy_sorted_groups)|n}
</script>
</%def>
<%def name="make_this_page_component()">
${parent.make_this_page_component()}
<script type="text/javascript">
Vue.component('find-principals', { Vue.component('find-principals', {
template: '#find-principals-template', template: '#find-principals-template',
@ -175,15 +187,8 @@ ${h.end_form()}
} }
}) })
new Vue({ </script>
el: '#find-principals-app', </%def>
data() {
return {
permissionGroups: ${json.dumps(buefy_perms)|n},
sortedGroups: ${json.dumps(buefy_sorted_groups)|n}
}
}
})
</script>
% endif ${parent.body()}

View file

@ -1,5 +1,5 @@
## -*- coding: utf-8; -*- ## -*- coding: utf-8; -*-
<%inherit file="/base.mako" /> <%inherit file="/page.mako" />
<%def name="title()">${index_title}</%def> <%def name="title()">${index_title}</%def>
@ -56,9 +56,7 @@
% endif % endif
</%def> </%def>
<%def name="page_content()">
<div style="display: flex; justify-content: space-between;">
% if use_form: % if use_form:
<div class="form-wrapper"> <div class="form-wrapper">
<p>Please select the type of report you wish to generate.</p> <p>Please select the type of report you wish to generate.</p>
@ -81,9 +79,7 @@
</div> </div>
</div> </div>
% endif % endif
</%def>
<ul id="context-menu">
${self.context_menu_items()}
</ul>
</div> ${parent.body()}

View file

@ -6,17 +6,22 @@
${h.stylesheet_link(request.static_url('tailbone:static/css/perms.css'))} ${h.stylesheet_link(request.static_url('tailbone:static/css/perms.css'))}
</%def> </%def>
${parent.body()} <%def name="page_content()">
${parent.page_content()}
<h2>Users</h2> <h2>Users</h2>
% if instance is guest_role: % if instance is guest_role:
<p>The guest role is implied for all anonymous users, i.e. when not logged in.</p> <p>The guest role is implied for all anonymous users, i.e. when not logged in.</p>
% elif instance is authenticated_role: % elif instance is authenticated_role:
<p>The authenticated role is implied for all users, but only when logged in.</p> <p>The authenticated role is implied for all users, but only when logged in.</p>
% elif users: % elif users:
<p>The following users are assigned to this role:</p> <p>The following users are assigned to this role:</p>
${users.render_grid()|n} ${users.render_grid()|n}
% else: % else:
<p>There are no users assigned to this role.</p> <p>There are no users assigned to this role.</p>
% endif % endif
</%def>
${parent.body()}

View file

@ -41,9 +41,8 @@
<email-preview-tools></email-preview-tools> <email-preview-tools></email-preview-tools>
</%def> </%def>
<%def name="render_this_page_template()">
% if use_buefy: ${parent.render_this_page_template()}
<script type="text/x-template" id="email-preview-tools-template"> <script type="text/x-template" id="email-preview-tools-template">
${h.form(url('email.preview'), **{'@submit': 'submitPreviewForm'})} ${h.form(url('email.preview'), **{'@submit': 'submitPreviewForm'})}
@ -106,7 +105,10 @@
${h.end_form()} ${h.end_form()}
</script> </script>
</%def>
<%def name="make_this_page_component()">
${parent.make_this_page_component()}
<script type="text/javascript"> <script type="text/javascript">
const EmailPreviewTools = { const EmailPreviewTools = {
@ -128,7 +130,7 @@
Vue.component('email-preview-tools', EmailPreviewTools) Vue.component('email-preview-tools', EmailPreviewTools)
</script> </script>
</%def>
% endif
${parent.body()} ${parent.body()}

View file

@ -1,8 +1,8 @@
## -*- coding: utf-8 -*- ## -*- coding: utf-8 -*-
<%inherit file="/master/create.mako" /> <%inherit file="/master/create.mako" />
<%def name="head_tags()"> <%def name="extra_javascript()">
${parent.head_tags()} ${parent.extra_javascript()}
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {

View file

@ -146,8 +146,8 @@
% endif % endif
</%def> </%def>
<%def name="modify_this_page()"> <%def name="modify_this_page_vars()">
${parent.modify_this_page()} ${parent.modify_this_page_vars()}
<script type="text/javascript"> <script type="text/javascript">
ThisPage.data = function() { return { ThisPage.data = function() { return {

View file

@ -258,7 +258,20 @@
% endfor % endfor
% endif % endif
## ##############################
## whole page
## ##############################
${self.body()} ${self.body()}
<div id="whole-page-app">
<whole-page></whole-page>
</div>
${self.render_whole_page_template()}
${self.make_whole_page_component()}
${self.make_whole_page_app()}
</section> </section>
## Footer ## Footer
@ -411,6 +424,59 @@
<%def name="head_tags()"></%def> <%def name="head_tags()"></%def>
<%def name="render_whole_page_template()">
<script type="text/x-template" id="whole-page-template">
<div>
<this-page></this-page>
</div>
</script>
</%def>
<%def name="declare_whole_page_vars()">
<script type="text/javascript">
let WholePage = {
template: '#whole-page-template',
methods: {}
}
let WholePageData = {}
</script>
</%def>
<%def name="modify_whole_page_vars()">
## NOTE: if you override this, must use <script> tags
</%def>
<%def name="finalize_whole_page_vars()">
## NOTE: if you override this, must use <script> tags
</%def>
<%def name="make_whole_page_component()">
${self.declare_whole_page_vars()}
${self.modify_whole_page_vars()}
${self.finalize_whole_page_vars()}
<script type="text/javascript">
WholePage.data = function() { return WholePageData }
Vue.component('whole-page', WholePage)
</script>
</%def>
<%def name="make_whole_page_app()">
<script type="text/javascript">
new Vue({
el: '#whole-page-app'
})
</script>
</%def>
<%def name="wtfield(form, name, **kwargs)"> <%def name="wtfield(form, name, **kwargs)">
<div class="field-wrapper${' error' if form[name].errors else ''}"> <div class="field-wrapper${' error' if form[name].errors else ''}">
<label for="${name}">${form[name].label}</label> <label for="${name}">${form[name].label}</label>

View file

@ -67,8 +67,8 @@
% endif % endif
</%def> </%def>
<%def name="modify_this_page()"> <%def name="modify_this_page_vars()">
${parent.modify_this_page()} ${parent.modify_this_page_vars()}
<script type="text/javascript"> <script type="text/javascript">
TailboneFormData.showingPackages = 'diffs' TailboneFormData.showingPackages = 'diffs'

View file

@ -38,7 +38,6 @@ from rattail.bouncer.config import get_profile_keys
from pyramid.response import FileResponse from pyramid.response import FileResponse
from webhelpers2.html import HTML, tags from webhelpers2.html import HTML, tags
from tailbone import grids
from tailbone.views import MasterView from tailbone.views import MasterView
@ -76,18 +75,17 @@ class EmailBouncesView(MasterView):
def configure_grid(self, g): def configure_grid(self, g):
super(EmailBouncesView, self).configure_grid(g) super(EmailBouncesView, self).configure_grid(g)
g.joiners['processed_by'] = lambda q: q.outerjoin(model.User) g.filters['config_key'].set_choices(self.handler_options)
g.filters['config_key'].default_active = True g.filters['config_key'].default_active = True
g.filters['config_key'].default_verb = 'equal' g.filters['config_key'].default_verb = 'equal'
g.filters['config_key'].set_value_renderer(grids.filters.ChoiceValueRenderer(self.handler_options)) g.joiners['processed_by'] = lambda q: q.outerjoin(model.User)
g.filters['processed'].default_active = True g.filters['processed'].default_active = True
g.filters['processed'].default_verb = 'is_null' g.filters['processed'].default_verb = 'is_null'
g.filters['processed_by'] = g.make_filter('processed_by', model.User.username) g.filters['processed_by'] = g.make_filter('processed_by', model.User.username)
g.sorters['processed_by'] = g.make_sorter(model.User.username) g.sorters['processed_by'] = g.make_sorter(model.User.username)
g.set_sort_defaults('bounced', 'desc') g.set_sort_defaults('bounced', 'desc')
g.set_label('config_key', "Source")
g.set_label('bounce_recipient_address', "Bounced To") g.set_label('bounce_recipient_address', "Bounced To")
g.set_label('intended_recipient_address', "Intended For") g.set_label('intended_recipient_address', "Intended For")

View file

@ -217,8 +217,8 @@ class PeopleView(MasterView):
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: if use_buefy:
return HTML.tag('button', type='button', class_='button is-primary', return HTML.tag('b-button', type='is-primary', c="Make User",
id='make-user', c="Make User") **{'@click': 'clickMakeUser()'})
else: else:
return HTML.tag('button', type='button', id='make-user', c="Make User") return HTML.tag('button', type='button', id='make-user', c="Make User")
else: else: