tailbone/tailbone/templates/themes/waterpark/base.mako

488 lines
15 KiB
Mako

## -*- coding: utf-8; -*-
<%inherit file="wuttaweb:templates/base.mako" />
<%namespace name="base_meta" file="/base_meta.mako" />
<%namespace file="/formposter.mako" import="declare_formposter_mixin" />
<%namespace file="/grids/filter-components.mako" import="make_grid_filter_components" />
<%namespace name="page_help" file="/page_help.mako" />
<%def name="base_styles()">
${parent.base_styles()}
<style>
.filters .filter-fieldname .field,
.filters .filter-fieldname .field label {
width: 100%;
}
.filters .filter-fieldname,
.filters .filter-fieldname .field label,
.filters .filter-fieldname .button {
justify-content: left;
}
.filters .filter-verb .select,
.filters .filter-verb .select select {
width: 100%;
}
% if filter_fieldname_width is not Undefined:
.filters .filter-fieldname,
.filters .filter-fieldname .button {
min-width: ${filter_fieldname_width};
}
.filters .filter-verb {
min-width: ${filter_verb_width};
}
% endif
</style>
</%def>
<%def name="before_content()">
## TODO: this must come before the self.body() call..but why?
${declare_formposter_mixin()}
</%def>
<%def name="render_navbar_brand()">
<div class="navbar-brand">
<a class="navbar-item" href="${url('home')}"
v-show="!menuSearchActive">
<div style="display: flex; align-items: center;">
${base_meta.header_logo()}
<div id="navbar-brand-title">
${base_meta.global_title()}
</div>
</div>
</a>
<div v-show="menuSearchActive"
class="navbar-item">
<b-autocomplete ref="menuSearchAutocomplete"
v-model="menuSearchTerm"
:data="menuSearchFilteredData"
field="label"
open-on-focus
keep-first
icon-pack="fas"
clearable
@keydown.native="menuSearchKeydown"
@select="menuSearchSelect">
</b-autocomplete>
</div>
<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_start()">
<div class="navbar-start">
<div v-if="menuSearchData.length"
class="navbar-item">
<b-button type="is-primary"
size="is-small"
@click="menuSearchInit()">
<span><i class="fa fa-search"></i></span>
</b-button>
</div>
% 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_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)}
<input type="hidden" name="referrer" :value="referrer" />
<div style="display: flex; align-items: center; gap: 0.5rem;">
<span>Theme:</span>
<b-select name="theme"
v-model="globalTheme"
@input="changeTheme()">
% for option in theme_picker_options:
<option value="${option.value}">
${option.label}
</option>
% endfor
</b-select>
</div>
${h.end_form()}
</div>
% endif
</%def>
<%def name="render_feedback_button()">
<div class="level-item">
<page-help
% if can_edit_help:
@configure-fields-help="configureFieldsHelp = true"
% endif
/>
</div>
% if request.has_perm('common.feedback'):
<feedback-form
action="${url('feedback')}"
:message="feedbackMessage">
</feedback-form>
% endif
</%def>
<%def name="render_this_page_component()">
<this-page @change-content-title="changeContentTitle"
% if can_edit_help:
:configure-fields-help="configureFieldsHelp"
% endif
/>
</%def>
<%def name="render_vue_templates()">
${parent.render_vue_templates()}
${page_help.render_template()}
${page_help.declare_vars()}
% if request.has_perm('common.feedback'):
<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="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 class="block">
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>
% if config.get_bool('tailbone.feedback_allows_reply'):
<div class="level">
<div class="level-left">
<div class="level-item">
<b-checkbox v-model="pleaseReply"
@input="pleaseReplyChanged">
Please email me back{{ pleaseReply ? " at: " : "" }}
</b-checkbox>
</div>
<div class="level-item" v-show="pleaseReply">
<b-input v-model="userEmail"
ref="userEmail">
</b-input>
</div>
</div>
</div>
% endif
</section>
<footer class="modal-card-foot">
<b-button @click="showDialog = false">
Cancel
</b-button>
<b-button type="is-primary"
icon-pack="fas"
icon-left="paper-plane"
@click="sendFeedback()"
:disabled="sendingFeedback || !message.trim()">
{{ sendingFeedback ? "Working, please wait..." : "Send Message" }}
</b-button>
</footer>
</div>
</b-modal>
</div>
</script>
<script>
const FeedbackForm = {
template: '#feedback-template',
mixins: [SimpleRequestMixin],
props: [
'action',
'message',
],
methods: {
showFeedback() {
this.referrer = location.href
this.showDialog = true
this.$nextTick(function() {
this.$refs.textarea.focus()
})
},
% if config.get_bool('tailbone.feedback_allows_reply'):
pleaseReplyChanged(value) {
this.$nextTick(() => {
this.$refs.userEmail.focus()
})
},
% endif
sendFeedback() {
this.sendingFeedback = true
const params = {
referrer: this.referrer,
user: this.userUUID,
user_name: this.userName,
% if config.get_bool('tailbone.feedback_allows_reply'):
please_reply_to: this.pleaseReply ? this.userEmail : null,
% endif
message: this.message.trim(),
}
this.simplePOST(this.action, params, response => {
this.$buefy.toast.open({
message: "Message sent! Thank you for your feedback.",
type: 'is-info',
duration: 4000, // 4 seconds
})
this.showDialog = false
// clear out message, in case they need to send another
this.message = ""
this.sendingFeedback = false
}, response => { // failure
this.sendingFeedback = false
})
},
}
}
const FeedbackFormData = {
referrer: null,
userUUID: null,
userName: null,
userEmail: null,
% if config.get_bool('tailbone.feedback_allows_reply'):
pleaseReply: false,
% endif
showDialog: false,
sendingFeedback: false,
}
</script>
% endif
</%def>
<%def name="modify_vue_vars()">
${parent.modify_vue_vars()}
<script>
##############################
## menu search
##############################
WholePageData.menuSearchActive = false
WholePageData.menuSearchTerm = ''
WholePageData.menuSearchData = ${json.dumps(global_search_data or [])|n}
WholePage.computed.menuSearchFilteredData = function() {
if (!this.menuSearchTerm.length) {
return this.menuSearchData
}
const terms = []
for (let term of this.menuSearchTerm.toLowerCase().split(' ')) {
term = term.trim()
if (term) {
terms.push(term)
}
}
if (!terms.length) {
return this.menuSearchData
}
// all terms must match
return this.menuSearchData.filter((option) => {
const label = option.label.toLowerCase()
for (const term of terms) {
if (label.indexOf(term) < 0) {
return false
}
}
return true
})
}
WholePage.methods.globalKey = function(event) {
// Ctrl+8 opens menu search
if (event.target.tagName == 'BODY') {
if (event.ctrlKey && event.key == '8') {
this.menuSearchInit()
}
}
}
WholePage.mounted = function() {
window.addEventListener('keydown', this.globalKey)
for (let hook of this.mountedHooks) {
hook(this)
}
}
WholePage.beforeDestroy = function() {
window.removeEventListener('keydown', this.globalKey)
}
WholePage.methods.menuSearchInit = function() {
this.menuSearchTerm = ''
this.menuSearchActive = true
this.$nextTick(() => {
this.$refs.menuSearchAutocomplete.focus()
})
}
WholePage.methods.menuSearchKeydown = function(event) {
// ESC will dismiss searchbox
if (event.which == 27) {
this.menuSearchActive = false
}
}
WholePage.methods.menuSearchSelect = function(option) {
location.href = option.url
}
##############################
## theme picker
##############################
% if expose_theme_picker and request.has_perm('common.change_app_theme'):
WholePageData.globalTheme = ${json.dumps(theme or None)|n}
## WholePageData.referrer = location.href
WholePage.methods.changeTheme = function() {
this.$refs.themePickerForm.submit()
}
% endif
##############################
## feedback
##############################
% if request.has_perm('common.feedback'):
WholePageData.feedbackMessage = ""
% if request.user:
FeedbackFormData.userUUID = ${json.dumps(request.user.uuid)|n}
FeedbackFormData.userName = ${json.dumps(str(request.user))|n}
% endif
% endif
##############################
## edit fields help
##############################
% if can_edit_help:
WholePageData.configureFieldsHelp = false
% endif
</script>
</%def>
<%def name="make_vue_components()">
${parent.make_vue_components()}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.datepicker.js') + f'?ver={tailbone.__version__}')}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.numericinput.js') + f'?ver={tailbone.__version__}')}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.oncebutton.js') + f'?ver={tailbone.__version__}')}
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.buefy.timepicker.js') + f'?ver={tailbone.__version__}')}
${make_grid_filter_components()}
${page_help.make_component()}
% if request.has_perm('common.feedback'):
<script>
FeedbackForm.data = function() { return FeedbackFormData }
Vue.component('feedback-form', FeedbackForm)
</script>
% endif
</%def>