Bring all of header into WholePage component
now there is only *one* Vue.js app instantiated on each page, yay!
This commit is contained in:
parent
47c2742878
commit
6d846ab0db
|
@ -1,6 +1,5 @@
|
|||
## -*- coding: utf-8; -*-
|
||||
<%namespace file="/grids/nav.mako" import="grid_index_nav" />
|
||||
<%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" />
|
||||
<!DOCTYPE html>
|
||||
|
@ -31,185 +30,6 @@
|
|||
</head>
|
||||
|
||||
<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>
|
||||
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="${url('home')}">
|
||||
${base_meta.header_logo()}
|
||||
${base_meta.global_title()}
|
||||
</a>
|
||||
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
|
||||
% for topitem in menus:
|
||||
% if topitem.is_link:
|
||||
${h.link_to(topitem.title, topitem.url, target=topitem.target, class_='navbar-item')}
|
||||
% else:
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link">${topitem.title}</a>
|
||||
<div class="navbar-dropdown">
|
||||
% for subitem in topitem.items:
|
||||
% if subitem.is_sep:
|
||||
<hr class="navbar-divider">
|
||||
% else:
|
||||
${h.link_to(subitem.title, subitem.url, class_='navbar-item', target=subitem.target)}
|
||||
% endif
|
||||
% endfor
|
||||
</div>
|
||||
</div>
|
||||
% endif
|
||||
% endfor
|
||||
|
||||
</div><!-- navbar-start -->
|
||||
<div class="navbar-end">
|
||||
|
||||
## User Menu
|
||||
% if request.user:
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
% if messaging_enabled:
|
||||
<a class="navbar-link ${'root-user' if request.is_root else ''}">${request.user}${" ({})".format(inbox_count) if inbox_count else ''}</a>
|
||||
% else:
|
||||
<a class="navbar-link ${'root-user' if request.is_root else ''}">${request.user}</a>
|
||||
% endif
|
||||
<div class="navbar-dropdown">
|
||||
% if request.is_root:
|
||||
${h.link_to("Stop being root", url('stop_root'), class_='navbar-item root-user')}
|
||||
% elif request.is_admin:
|
||||
${h.link_to("Become root", url('become_root'), class_='navbar-item root-user')}
|
||||
% endif
|
||||
% if messaging_enabled:
|
||||
${h.link_to("Messages{}".format(" ({})".format(inbox_count) if inbox_count else ''), url('messages.inbox'), class_='navbar-item')}
|
||||
% endif
|
||||
${h.link_to("Change Password", url('change_password'), class_='navbar-item')}
|
||||
${h.link_to("Logout", url('logout'), class_='navbar-item')}
|
||||
</div>
|
||||
</div>
|
||||
% else:
|
||||
${h.link_to("Login", url('login'), class_='navbar-item')}
|
||||
% endif
|
||||
|
||||
</div><!-- navbar-end -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<nav class="level" style="margin: 0.5rem auto;">
|
||||
<div class="level-left">
|
||||
|
||||
## Current Context
|
||||
<div id="current-context" class="level-item">
|
||||
% if master:
|
||||
% if master.listing:
|
||||
<span>${index_title}</span>
|
||||
% else:
|
||||
${h.link_to(index_title, index_url)}
|
||||
% if parent_url is not Undefined:
|
||||
<span>»</span>
|
||||
${h.link_to(parent_title, parent_url)}
|
||||
% elif instance_url is not Undefined:
|
||||
<span>»</span>
|
||||
${h.link_to(instance_title, instance_url)}
|
||||
% endif
|
||||
% if master.viewing and grid_index:
|
||||
${grid_index_nav()}
|
||||
% endif
|
||||
% endif
|
||||
% elif index_title:
|
||||
<span>${index_title}</span>
|
||||
% endif
|
||||
</div>
|
||||
|
||||
% if expose_db_picker is not Undefined and expose_db_picker:
|
||||
<div class="level-item">
|
||||
<p>DB:</p>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
${h.form(url('change_db_engine'))}
|
||||
${h.csrf_token(request)}
|
||||
${h.hidden('engine_type', value=master.engine_type_key)}
|
||||
<div class="select">
|
||||
${h.select('dbkey', db_picker_selected, db_picker_options, id='db-picker')}
|
||||
</div>
|
||||
${h.end_form()}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
</div><!-- level-left -->
|
||||
<div class="level-right">
|
||||
|
||||
## Quickie Lookup
|
||||
% if quickie is not Undefined and quickie and request.has_perm(quickie.perm):
|
||||
<div class="level-item">
|
||||
${h.form(quickie.url, method="get")}
|
||||
<div class="level">
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
${h.text('entry', placeholder=quickie.placeholder, autocomplete='off')}
|
||||
</div>
|
||||
<div class="level-item">
|
||||
<button type="submit" class="button is-primary">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-search"></i>
|
||||
</span>
|
||||
<span>Lookup</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
${h.end_form()}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
## Theme Picker
|
||||
% if expose_theme_picker and request.has_perm('common.change_app_theme'):
|
||||
<div class="level-item">
|
||||
${h.form(url('change_theme'), method="post")}
|
||||
${h.csrf_token(request)}
|
||||
Theme:
|
||||
<div class="theme-picker">
|
||||
<div class="select">
|
||||
${h.select('theme', theme, options=theme_picker_options, id='theme-picker')}
|
||||
</div>
|
||||
</div>
|
||||
${h.end_form()}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
## Help Button
|
||||
% if help_url is not Undefined and help_url:
|
||||
<div class="level-item">
|
||||
${h.link_to("Help", help_url, target='_blank', class_='button')}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
## Feedback Button / Dialog
|
||||
${h.javascript_link(request.static_url('tailbone:static/themes/falafel/js/tailbone.feedback.js') + '?ver={}'.format(tailbone.__version__))}
|
||||
${feedback_dialog()}
|
||||
<div id="feedback-app">
|
||||
<feedback-form action="${url('feedback')}">
|
||||
</feedback-form>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
new Vue({el: '#feedback-app'})
|
||||
</script>
|
||||
|
||||
</div><!-- level-right -->
|
||||
</nav><!-- level -->
|
||||
</header>
|
||||
|
||||
${self.body()}
|
||||
|
||||
<div id="whole-page-app">
|
||||
|
@ -219,7 +39,6 @@
|
|||
${self.render_whole_page_template()}
|
||||
${self.make_whole_page_component()}
|
||||
${self.make_whole_page_app()}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -268,20 +87,6 @@
|
|||
var session_timeout = ${request.get_session_timeout() or 'null'};
|
||||
var logout_url = '${request.route_url('logout')}';
|
||||
var noop_url = '${request.route_url('noop')}';
|
||||
% if expose_db_picker is not Undefined and expose_db_picker:
|
||||
$(function() {
|
||||
$('#db-picker').change(function() {
|
||||
$(this).parents('form:first').submit();
|
||||
});
|
||||
});
|
||||
% endif
|
||||
% if expose_theme_picker and request.has_perm('common.change_app_theme'):
|
||||
$(function() {
|
||||
$('#theme-picker').change(function() {
|
||||
$(this).parents('form:first').submit();
|
||||
});
|
||||
});
|
||||
% endif
|
||||
$(function() {
|
||||
## NOTE: this code was copied from
|
||||
## https://bulma.io/documentation/components/navbar/#navbar-menu
|
||||
|
@ -364,6 +169,173 @@
|
|||
<%def name="render_whole_page_template()">
|
||||
<script type="text/x-template" id="whole-page-template">
|
||||
<div>
|
||||
<header>
|
||||
|
||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="${url('home')}">
|
||||
${base_meta.header_logo()}
|
||||
${base_meta.global_title()}
|
||||
</a>
|
||||
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-start">
|
||||
|
||||
% for topitem in menus:
|
||||
% if topitem.is_link:
|
||||
${h.link_to(topitem.title, topitem.url, target=topitem.target, class_='navbar-item')}
|
||||
% else:
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
<a class="navbar-link">${topitem.title}</a>
|
||||
<div class="navbar-dropdown">
|
||||
% for subitem in topitem.items:
|
||||
% if subitem.is_sep:
|
||||
<hr class="navbar-divider">
|
||||
% else:
|
||||
${h.link_to(subitem.title, subitem.url, class_='navbar-item', target=subitem.target)}
|
||||
% endif
|
||||
% endfor
|
||||
</div>
|
||||
</div>
|
||||
% endif
|
||||
% endfor
|
||||
|
||||
</div><!-- navbar-start -->
|
||||
<div class="navbar-end">
|
||||
|
||||
## User Menu
|
||||
% if request.user:
|
||||
<div class="navbar-item has-dropdown is-hoverable">
|
||||
% if messaging_enabled:
|
||||
<a class="navbar-link ${'root-user' if request.is_root else ''}">${request.user}${" ({})".format(inbox_count) if inbox_count else ''}</a>
|
||||
% else:
|
||||
<a class="navbar-link ${'root-user' if request.is_root else ''}">${request.user}</a>
|
||||
% endif
|
||||
<div class="navbar-dropdown">
|
||||
% if request.is_root:
|
||||
${h.link_to("Stop being root", url('stop_root'), class_='navbar-item root-user')}
|
||||
% elif request.is_admin:
|
||||
${h.link_to("Become root", url('become_root'), class_='navbar-item root-user')}
|
||||
% endif
|
||||
% if messaging_enabled:
|
||||
${h.link_to("Messages{}".format(" ({})".format(inbox_count) if inbox_count else ''), url('messages.inbox'), class_='navbar-item')}
|
||||
% endif
|
||||
${h.link_to("Change Password", url('change_password'), class_='navbar-item')}
|
||||
${h.link_to("Logout", url('logout'), class_='navbar-item')}
|
||||
</div>
|
||||
</div>
|
||||
% else:
|
||||
${h.link_to("Login", url('login'), class_='navbar-item')}
|
||||
% endif
|
||||
|
||||
</div><!-- navbar-end -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<nav class="level" style="margin: 0.5rem auto;">
|
||||
<div class="level-left">
|
||||
|
||||
## Current Context
|
||||
<div id="current-context" class="level-item">
|
||||
% if master:
|
||||
% if master.listing:
|
||||
<span>${index_title}</span>
|
||||
% else:
|
||||
${h.link_to(index_title, index_url)}
|
||||
% if parent_url is not Undefined:
|
||||
<span>»</span>
|
||||
${h.link_to(parent_title, parent_url)}
|
||||
% elif instance_url is not Undefined:
|
||||
<span>»</span>
|
||||
${h.link_to(instance_title, instance_url)}
|
||||
% endif
|
||||
% if master.viewing and grid_index:
|
||||
${grid_index_nav()}
|
||||
% endif
|
||||
% endif
|
||||
% elif index_title:
|
||||
<span>${index_title}</span>
|
||||
% endif
|
||||
</div>
|
||||
|
||||
% if expose_db_picker is not Undefined and expose_db_picker:
|
||||
<div class="level-item">
|
||||
<p>DB:</p>
|
||||
</div>
|
||||
<div class="level-item">
|
||||
${h.form(url('change_db_engine'), ref='dbPickerForm')}
|
||||
${h.csrf_token(request)}
|
||||
${h.hidden('engine_type', value=master.engine_type_key)}
|
||||
<div class="select">
|
||||
${h.select('dbkey', db_picker_selected, db_picker_options, **{'@change': 'changeDB()'})}
|
||||
</div>
|
||||
${h.end_form()}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
</div><!-- level-left -->
|
||||
<div class="level-right">
|
||||
|
||||
## Quickie Lookup
|
||||
% if quickie is not Undefined and quickie and request.has_perm(quickie.perm):
|
||||
<div class="level-item">
|
||||
${h.form(quickie.url, method="get")}
|
||||
<div class="level">
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
${h.text('entry', placeholder=quickie.placeholder, autocomplete='off')}
|
||||
</div>
|
||||
<div class="level-item">
|
||||
<button type="submit" class="button is-primary">
|
||||
<span class="icon is-small">
|
||||
<i class="fas fa-search"></i>
|
||||
</span>
|
||||
<span>Lookup</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
${h.end_form()}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
## Theme Picker
|
||||
% if expose_theme_picker and request.has_perm('common.change_app_theme'):
|
||||
<div class="level-item">
|
||||
${h.form(url('change_theme'), method="post", ref='themePickerForm')}
|
||||
${h.csrf_token(request)}
|
||||
Theme:
|
||||
<div class="theme-picker">
|
||||
<div class="select">
|
||||
${h.select('theme', theme, theme_picker_options, **{'@change': 'changeTheme()'})}
|
||||
</div>
|
||||
</div>
|
||||
${h.end_form()}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
## Help Button
|
||||
% if help_url is not Undefined and help_url:
|
||||
<div class="level-item">
|
||||
${h.link_to("Help", help_url, target='_blank', class_='button')}
|
||||
</div>
|
||||
% endif
|
||||
|
||||
## Feedback Button / Dialog
|
||||
<feedback-form
|
||||
action="${url('feedback')}">
|
||||
</feedback-form>
|
||||
|
||||
</div><!-- level-right -->
|
||||
</nav><!-- level -->
|
||||
</header>
|
||||
|
||||
## Page Title
|
||||
<section id="content-title" class="hero is-primary">
|
||||
|
@ -397,19 +369,17 @@
|
|||
|
||||
% if request.session.peek_flash('error'):
|
||||
% for error in request.session.pop_flash('error'):
|
||||
<div class="notification is-warning">
|
||||
<!-- <button class="delete"></button> -->
|
||||
<b-notification type="is-warning">
|
||||
${error}
|
||||
</div>
|
||||
</b-notification>
|
||||
% endfor
|
||||
% endif
|
||||
|
||||
% if request.session.peek_flash():
|
||||
% for msg in request.session.pop_flash():
|
||||
<div class="notification is-info">
|
||||
<!-- <button class="delete"></button> -->
|
||||
<b-notification type="is-info">
|
||||
${msg}
|
||||
</div>
|
||||
</b-notification>
|
||||
% endfor
|
||||
% endif
|
||||
|
||||
|
@ -428,17 +398,101 @@
|
|||
</div><!-- content-wrapper -->
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-template" id="feedback-template">
|
||||
<div>
|
||||
|
||||
<div class="level-item">
|
||||
<b-button type="is-primary"
|
||||
@click="showFeedback()"
|
||||
icon-pack="fas"
|
||||
icon-left="fas fa-comment">
|
||||
Feedback
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<b-modal has-modal-card
|
||||
:active.sync="showDialog">
|
||||
<div class="modal-card">
|
||||
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">User Feedback</p>
|
||||
</header>
|
||||
|
||||
<section class="modal-card-body">
|
||||
<p>
|
||||
Questions, suggestions, comments, complaints, etc.
|
||||
<span class="red">regarding this website</span> are
|
||||
welcome and may be submitted below.
|
||||
</p>
|
||||
|
||||
<b-field label="User Name">
|
||||
<b-input v-model="userName"
|
||||
% if request.user:
|
||||
disabled
|
||||
% endif
|
||||
>
|
||||
</b-input>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Referring URL">
|
||||
<b-input
|
||||
v-model="referrer"
|
||||
disabled="true">
|
||||
</b-input>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Message">
|
||||
<b-input type="textarea"
|
||||
v-model="message"
|
||||
ref="textarea">
|
||||
</b-input>
|
||||
</b-field>
|
||||
|
||||
</section>
|
||||
|
||||
<footer class="modal-card-foot">
|
||||
<b-button @click="showDialog = false">
|
||||
Cancel
|
||||
</b-button>
|
||||
<once-button type="is-primary"
|
||||
@click="sendFeedback()"
|
||||
:disabled="!message.trim()"
|
||||
text="Send Message">
|
||||
</once-button>
|
||||
</footer>
|
||||
</div>
|
||||
</b-modal>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
${tailbone_autocomplete_template()}
|
||||
</%def>
|
||||
|
||||
<%def name="declare_whole_page_vars()">
|
||||
${h.javascript_link(request.static_url('tailbone:static/themes/falafel/js/tailbone.feedback.js') + '?ver={}'.format(tailbone.__version__))}
|
||||
<script type="text/javascript">
|
||||
|
||||
let WholePage = {
|
||||
template: '#whole-page-template',
|
||||
methods: {
|
||||
|
||||
changeContentTitle(newTitle) {
|
||||
this.contentTitleHTML = newTitle
|
||||
}
|
||||
},
|
||||
|
||||
% if expose_db_picker is not Undefined and expose_db_picker:
|
||||
changeDB() {
|
||||
this.$refs.dbPickerForm.submit()
|
||||
},
|
||||
% endif
|
||||
|
||||
% if expose_theme_picker and request.has_perm('common.change_app_theme'):
|
||||
changeTheme() {
|
||||
this.$refs.themePickerForm.submit()
|
||||
},
|
||||
% endif
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -450,7 +504,17 @@
|
|||
</%def>
|
||||
|
||||
<%def name="modify_whole_page_vars()">
|
||||
## NOTE: if you override this, must use <script> tags
|
||||
<script type="text/javascript">
|
||||
|
||||
FeedbackFormData.csrftoken = ${json.dumps(request.session.get_csrf_token() or request.session.new_csrf_token())|n}
|
||||
FeedbackFormData.referrer = location.href
|
||||
|
||||
% if request.user:
|
||||
FeedbackFormData.userUUID = ${json.dumps(request.user.uuid)|n}
|
||||
FeedbackFormData.userName = ${json.dumps(six.text_type(request.user))|n}
|
||||
% endif
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="finalize_whole_page_vars()">
|
||||
|
@ -462,8 +526,14 @@
|
|||
${self.modify_whole_page_vars()}
|
||||
${self.finalize_whole_page_vars()}
|
||||
|
||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.autocomplete.js') + '?ver={}'.format(tailbone.__version__))}
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
FeedbackForm.data = function() { return FeedbackFormData }
|
||||
|
||||
Vue.component('feedback-form', FeedbackForm)
|
||||
|
||||
WholePage.data = function() { return WholePageData }
|
||||
|
||||
Vue.component('whole-page', WholePage)
|
||||
|
|
Loading…
Reference in a new issue