feat: split up base templates into more sections (def blocks)
partly to allow easier customization, partly just for clarity
This commit is contained in:
parent
fce0de5d30
commit
869963403d
|
@ -15,6 +15,10 @@
|
||||||
<whole-page />
|
<whole-page />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## nb. sometimes a template needs to define something
|
||||||
|
## before the body content proper is rendered
|
||||||
|
${self.before_content()}
|
||||||
|
|
||||||
## content body from derived/child template
|
## content body from derived/child template
|
||||||
${self.body()}
|
${self.body()}
|
||||||
|
|
||||||
|
@ -26,8 +30,12 @@
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
## nb. this becomes part of the page <title> tag within <head>
|
||||||
|
## it also is used as default value for content_title() below
|
||||||
<%def name="title()"></%def>
|
<%def name="title()"></%def>
|
||||||
|
|
||||||
|
## nb. this is the "content title" as shown on screen, within the
|
||||||
|
## "hero bar" just below the "index title"
|
||||||
<%def name="content_title()">${self.title()}</%def>
|
<%def name="content_title()">${self.title()}</%def>
|
||||||
|
|
||||||
<%def name="header_core()">
|
<%def name="header_core()">
|
||||||
|
@ -41,7 +49,10 @@
|
||||||
${self.vuejs()}
|
${self.vuejs()}
|
||||||
${self.buefy()}
|
${self.buefy()}
|
||||||
${self.fontawesome()}
|
${self.fontawesome()}
|
||||||
|
${self.hamburger_menu_js()}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="hamburger_menu_js()">
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
## NOTE: this code was copied from
|
## NOTE: this code was copied from
|
||||||
|
@ -88,14 +99,21 @@
|
||||||
|
|
||||||
<%def name="core_styles()">
|
<%def name="core_styles()">
|
||||||
${self.buefy_styles()}
|
${self.buefy_styles()}
|
||||||
|
${self.base_styles()}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="buefy_styles()">
|
||||||
|
${h.stylesheet_link(h.get_liburl(request, 'buefy.css'))}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="base_styles()">
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
/* ****************************** */
|
##############################
|
||||||
/* page */
|
## page
|
||||||
/* ****************************** */
|
##############################
|
||||||
|
|
||||||
/* nb. helps force footer to bottom of screen */
|
## nb. helps force footer to bottom of screen
|
||||||
html, body {
|
html, body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -106,12 +124,14 @@
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
/* nb. this refers to the "menu-sized" app title in far left of main menu */
|
## nb. this refers to the "menu-sized" app title in far left of main menu
|
||||||
#global-header-title {
|
#navbar-brand-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#current-context {
|
#header-index-title {
|
||||||
|
display: flex;
|
||||||
|
gap: 1.5rem;
|
||||||
padding-left: 0.5rem;
|
padding-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,10 +152,6 @@
|
||||||
</style>
|
</style>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="buefy_styles()">
|
|
||||||
${h.stylesheet_link(h.get_liburl(request, 'buefy.css'))}
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
${base_meta.extra_styles()}
|
${base_meta.extra_styles()}
|
||||||
</%def>
|
</%def>
|
||||||
|
@ -144,80 +160,36 @@
|
||||||
|
|
||||||
<%def name="render_vue_template_whole_page()">
|
<%def name="render_vue_template_whole_page()">
|
||||||
<script type="text/x-template" id="whole-page-template">
|
<script type="text/x-template" id="whole-page-template">
|
||||||
|
|
||||||
|
## nb. the whole-page contains 3 elements:
|
||||||
|
## 1) header-wrapper
|
||||||
|
## 2) content-wrapper
|
||||||
|
## 3) footer
|
||||||
<div id="whole-page"
|
<div id="whole-page"
|
||||||
style="height: 100%; display: flex; flex-direction: column; justify-content: space-between;">
|
style="height: 100%; display: flex; flex-direction: column; justify-content: space-between;">
|
||||||
|
|
||||||
|
## nb. the header-wrapper contains 2 elements:
|
||||||
|
## 1) header proper (menu + index title area)
|
||||||
|
## 2) page/content title area
|
||||||
<div class="header-wrapper">
|
<div class="header-wrapper">
|
||||||
|
|
||||||
|
## nb. the header proper contains 2 elements:
|
||||||
|
## 1) menu bar
|
||||||
|
## 2) index title area
|
||||||
<header>
|
<header>
|
||||||
|
|
||||||
|
## nb. this is the main menu bar
|
||||||
<nav class="navbar" role="navigation" aria-label="main navigation">
|
<nav class="navbar" role="navigation" aria-label="main navigation">
|
||||||
|
${self.render_navbar_brand()}
|
||||||
<div class="navbar-brand">
|
${self.render_navbar_menu()}
|
||||||
<a class="navbar-item" href="${url('home')}">
|
|
||||||
<div style="display: flex; gap: 0.3rem; align-items: center;">
|
|
||||||
${base_meta.header_logo()}
|
|
||||||
<div id="global-header-title">
|
|
||||||
${base_meta.global_title()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a role="button" class="navbar-burger" data-target="navbar-menu" 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" id="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 item in topitem['items']:
|
|
||||||
% if item['is_menu']:
|
|
||||||
<% item_hash = id(item) %>
|
|
||||||
<% toggle = 'menu_{}_shown'.format(item_hash) %>
|
|
||||||
<div>
|
|
||||||
<a class="navbar-link" @click.prevent="toggleNestedMenu('${item_hash}')">
|
|
||||||
${item['title']}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
% for subitem in item['items']:
|
|
||||||
% if subitem['is_sep']:
|
|
||||||
<hr class="navbar-divider" v-show="${toggle}">
|
|
||||||
% else:
|
|
||||||
${h.link_to("{}".format(subitem['title']), subitem['url'], class_='navbar-item nested', target=subitem['target'], **{'v-show': toggle})}
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
% else:
|
|
||||||
% if item['is_sep']:
|
|
||||||
<hr class="navbar-divider">
|
|
||||||
% else:
|
|
||||||
${h.link_to(item['title'], item['url'], class_='navbar-item', target=item['target'])}
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
% endif
|
|
||||||
% endfor
|
|
||||||
|
|
||||||
</div><!-- navbar-start -->
|
|
||||||
${self.render_navbar_end()}
|
|
||||||
</div>
|
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
## nb. this is the "index title" area
|
||||||
<nav class="level" style="margin: 0.5rem 0.5rem 0.5rem auto;">
|
<nav class="level" style="margin: 0.5rem 0.5rem 0.5rem auto;">
|
||||||
<div class="level-left">
|
|
||||||
|
|
||||||
## Current Context
|
## nb. this is the index title proper
|
||||||
<div id="current-context" class="level-item"
|
<div class="level-left">
|
||||||
style="display: flex; gap: 1.5rem;">
|
<div id="header-index-title" class="level-item">
|
||||||
% if index_title:
|
% if index_title:
|
||||||
% if index_url:
|
% if index_url:
|
||||||
<h1 class="title">${h.link_to(index_title, index_url)}</h1>
|
<h1 class="title">${h.link_to(index_title, index_url)}</h1>
|
||||||
|
@ -232,11 +204,12 @@
|
||||||
% endif
|
% endif
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div><!-- level-left -->
|
## nb. this is a utility area for the master context
|
||||||
|
|
||||||
<div class="level-right">
|
<div class="level-right">
|
||||||
|
|
||||||
|
## Configure button
|
||||||
% if master and master.configurable and not master.configuring and master.has_perm('configure'):
|
% if master and master.configurable and not master.configuring and master.has_perm('configure'):
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<wutta-button once type="is-primary"
|
<wutta-button once type="is-primary"
|
||||||
|
@ -246,11 +219,14 @@
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
</div> <!-- level-right -->
|
${self.render_theme_picker()}
|
||||||
</nav><!-- level -->
|
${self.render_feedback_button()}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
## Page Title
|
## nb. the page / content title area (aka. hero bar)
|
||||||
% if capture(self.content_title):
|
% if capture(self.content_title):
|
||||||
<section id="content-title"
|
<section id="content-title"
|
||||||
class="has-background-primary">
|
class="has-background-primary">
|
||||||
|
@ -274,10 +250,9 @@
|
||||||
|
|
||||||
</div> <!-- header-wrapper -->
|
</div> <!-- header-wrapper -->
|
||||||
|
|
||||||
|
## nb. the page content area
|
||||||
<div class="content-wrapper"
|
<div class="content-wrapper"
|
||||||
style="flex-grow: 1; padding: 0.5rem;">
|
style="flex-grow: 1; padding: 0.5rem;">
|
||||||
|
|
||||||
## Page Body
|
|
||||||
<section id="page-body" style="height: 100%;">
|
<section id="page-body" style="height: 100%;">
|
||||||
|
|
||||||
% if request.session.peek_flash('error'):
|
% if request.session.peek_flash('error'):
|
||||||
|
@ -308,10 +283,9 @@
|
||||||
${self.render_this_page_component()}
|
${self.render_this_page_component()}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
</div><!-- content-wrapper -->
|
</div><!-- content-wrapper -->
|
||||||
|
|
||||||
## Footer
|
## nb. the page footer
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
${base_meta.footer()}
|
${base_meta.footer()}
|
||||||
|
@ -322,10 +296,87 @@
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_navbar_brand()">
|
||||||
|
<div class="navbar-brand">
|
||||||
|
<a class="navbar-item" href="${url('home')}">
|
||||||
|
<div style="display: flex; gap: 0.3rem; align-items: center;">
|
||||||
|
${base_meta.header_logo()}
|
||||||
|
<div id="navbar-brand-title">
|
||||||
|
${base_meta.global_title()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a role="button" class="navbar-burger" data-target="navbar-menu" aria-label="menu" aria-expanded="false">
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
<span aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_navbar_menu()">
|
||||||
|
<div class="navbar-menu" id="navbar-menu">
|
||||||
|
${self.render_navbar_start()}
|
||||||
|
${self.render_navbar_end()}
|
||||||
|
</div>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_navbar_start()">
|
||||||
|
<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 item in topitem['items']:
|
||||||
|
% if item['is_menu']:
|
||||||
|
<% item_hash = id(item) %>
|
||||||
|
<% toggle = 'menu_{}_shown'.format(item_hash) %>
|
||||||
|
<div>
|
||||||
|
<a class="navbar-link" @click.prevent="toggleNestedMenu('${item_hash}')">
|
||||||
|
${item['title']}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
% for subitem in item['items']:
|
||||||
|
% if subitem['is_sep']:
|
||||||
|
<hr class="navbar-divider" v-show="${toggle}">
|
||||||
|
% else:
|
||||||
|
${h.link_to("{}".format(subitem['title']), subitem['url'], class_='navbar-item nested', target=subitem['target'], **{'v-show': toggle})}
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
% else:
|
||||||
|
% if item['is_sep']:
|
||||||
|
<hr class="navbar-divider">
|
||||||
|
% else:
|
||||||
|
${h.link_to(item['title'], item['url'], class_='navbar-item', target=item['target'])}
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_navbar_end()">
|
||||||
|
<div class="navbar-end">
|
||||||
|
${self.render_user_menu()}
|
||||||
|
</div>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_theme_picker()"></%def>
|
||||||
|
|
||||||
|
<%def name="render_feedback_button()"></%def>
|
||||||
|
|
||||||
<%def name="render_vue_script_whole_page()">
|
<%def name="render_vue_script_whole_page()">
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
let WholePage = {
|
const WholePage = {
|
||||||
template: '#whole-page-template',
|
template: '#whole-page-template',
|
||||||
computed: {},
|
computed: {},
|
||||||
|
|
||||||
|
@ -360,8 +411,9 @@
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
let WholePageData = {
|
const WholePageData = {
|
||||||
contentTitleHTML: ${json.dumps(capture(self.content_title))|n},
|
contentTitleHTML: ${json.dumps(capture(self.content_title))|n},
|
||||||
|
referrer: location.href,
|
||||||
mountedHooks: [],
|
mountedHooks: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,16 +431,12 @@
|
||||||
</script>
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="before_content()"></%def>
|
||||||
|
|
||||||
<%def name="render_this_page_component()">
|
<%def name="render_this_page_component()">
|
||||||
<this-page @change-content-title="changeContentTitle" />
|
<this-page @change-content-title="changeContentTitle" />
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_navbar_end()">
|
|
||||||
<div class="navbar-end">
|
|
||||||
${self.render_user_menu()}
|
|
||||||
</div>
|
|
||||||
</%def>
|
|
||||||
|
|
||||||
<%def name="render_user_menu()">
|
<%def name="render_user_menu()">
|
||||||
% if request.user:
|
% if request.user:
|
||||||
<div class="navbar-item has-dropdown is-hoverable">
|
<div class="navbar-item has-dropdown is-hoverable">
|
||||||
|
@ -468,6 +516,10 @@
|
||||||
|
|
||||||
<%def name="render_prevnext_header_buttons()"></%def>
|
<%def name="render_prevnext_header_buttons()"></%def>
|
||||||
|
|
||||||
|
##############################
|
||||||
|
## vue components + app
|
||||||
|
##############################
|
||||||
|
|
||||||
<%def name="render_vue_templates()">
|
<%def name="render_vue_templates()">
|
||||||
${self.render_vue_template_whole_page()}
|
${self.render_vue_template_whole_page()}
|
||||||
${self.render_vue_script_whole_page()}
|
${self.render_vue_script_whole_page()}
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
|
|
||||||
<%def name="render_vue_templates()">
|
<%def name="render_vue_templates()">
|
||||||
${parent.render_vue_templates()}
|
${parent.render_vue_templates()}
|
||||||
|
${self.render_vue_template_grid()}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_vue_template_grid()">
|
||||||
% if grid is not Undefined:
|
% if grid is not Undefined:
|
||||||
${grid.render_vue_template()}
|
${grid.render_vue_template()}
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<%def name="render_vue_templates()">
|
<%def name="render_vue_templates()">
|
||||||
${parent.render_vue_templates()}
|
${parent.render_vue_templates()}
|
||||||
${self.render_vue_template_this_page()}
|
${self.render_vue_template_this_page()}
|
||||||
|
${self.render_vue_script_this_page()}
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="render_vue_template_this_page()">
|
<%def name="render_vue_template_this_page()">
|
||||||
|
@ -14,6 +15,9 @@
|
||||||
${self.page_content()}
|
${self.page_content()}
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_vue_script_this_page()">
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
const ThisPage = {
|
const ThisPage = {
|
||||||
|
|
Loading…
Reference in a new issue