diff --git a/tailbone/static/themes/falafel/css/layout.css b/tailbone/static/themes/falafel/css/layout.css new file mode 100644 index 00000000..5134141a --- /dev/null +++ b/tailbone/static/themes/falafel/css/layout.css @@ -0,0 +1,99 @@ + +/****************************** + * main layout + ******************************/ + +body { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.content-wrapper { + display: flex; + flex: 1; + flex-direction: column; + justify-content: space-between; +} + + +/****************************** + * header + ******************************/ + +header .level { + /* height: 60px; */ + line-height: 60px; + padding-left: 0.5em; + padding-right: 0.5em; +} + +header .level #header-logo { + display: inline-block; +} + +header .level .global-title, +header .level-left .global-title { + font-size: 2em; + font-weight: bold; +} + +header .level #current-context, +header .level-left #current-context { + font-size: 2em; + font-weight: bold; +} + +header .level #current-context span, +header .level-left #current-context span { + margin-right: 10px; +} + +header .level .theme-picker { + display: inline-flex; +} + +#content-title h1 { + font-size: 2em; +} + +/****************************** + * content + ******************************/ + +#page-body { + padding: 0.4em; +} + +/****************************** + * context menu + ******************************/ + +#context-menu { + text-align: right; + white-space: nowrap; +} + +/****************************** + * "object helper" panel + ******************************/ + +.object-helper { + border: 1px solid black; + margin: 1em; + padding: 1em; + width: 20em; +} + +.object-helper-content { + margin-top: 1em; +} + +/****************************** + * feedback + ******************************/ + +.feedback-dialog .red { + color: red; + font-weight: bold; +} diff --git a/tailbone/static/themes/falafel/js/tailbone.feedback.js b/tailbone/static/themes/falafel/js/tailbone.feedback.js new file mode 100644 index 00000000..d6da902b --- /dev/null +++ b/tailbone/static/themes/falafel/js/tailbone.feedback.js @@ -0,0 +1,59 @@ + +const FeedbackForm = { + props: ['user_name', 'referrer'], + template: '#feedback-template', + methods: { + sendFeedback() { + + var textarea = $('.feedback-dialog textarea'); + var msg = $.trim(textarea.val()); + if (! msg) { + alert("Please enter a message."); + textarea.select(); + textarea.focus(); + return; + } + + // disable_button(dialog_button(event)); + + var form = $('.feedback-dialog').parents('form'); + // TODO: this was copied from default template, but surely we could + // just serialize() the form instead? + var data = { + _csrf: form.find('input[name="_csrf"]').val(), + referrer: location.href, + user: form.find('input[name="user"]').val(), + user_name: form.find('input[name="user_name"]').val(), + message: msg + }; + + var that = this; + $.ajax(form.attr('action'), { + method: 'POST', + data: data, + success: function(data) { + that.$emit('close'); + alert("Message successfully sent.\n\nThank you for your feedback."); + } + }); + + } + } +} + +new Vue({ + el: '#feedback-app', + methods: { + showFeedback() { + this.$modal.open({ + parent: this, + canCancel: ['escape', 'x'], + component: FeedbackForm, + hasModalCard: true, + props: { + referrer: location.href + } + }); + } + } +}); diff --git a/tailbone/templates/themes/falafel/base.mako b/tailbone/templates/themes/falafel/base.mako new file mode 100644 index 00000000..77473d4e --- /dev/null +++ b/tailbone/templates/themes/falafel/base.mako @@ -0,0 +1,329 @@ +## -*- coding: utf-8; -*- +<%namespace file="/grids/nav.mako" import="grid_index_nav" /> +<%namespace file="/feedback_dialog.mako" import="feedback_dialog" /> +<%namespace name="base_meta" file="/base_meta.mako" /> + + + + + ${base_meta.global_title()} » ${capture(self.title)|n} + ${base_meta.favicon()} + ${self.header_core()} + + % if background_color: + + % endif + + % if not request.rattail_config.production(): + + % endif + + ${self.head_tags()} + + + +
+ + + + +
+ + ## Page Title +
+
+ % if capture(self.content_title): + + % if show_prev_next is not Undefined and show_prev_next: +
+ % if prev_url: + ${h.link_to("« Older", prev_url, class_='button autodisable')} + % else: + ${h.link_to("« Older", '#', class_='button', disabled='disabled')} + % endif + % if next_url: + ${h.link_to("Newer »", next_url, class_='button autodisable')} + % else: + ${h.link_to("Newer »", '#', class_='button', disabled='disabled')} + % endif +
+ % endif + +

${self.content_title()}

+ % endif +
+
+ +
+ + ## Page Body +
+ + % if request.session.peek_flash('error'): + % for error in request.session.pop_flash('error'): +
+ + ${error} +
+ % endfor + % endif + + % if request.session.peek_flash(): + % for msg in request.session.pop_flash(): +
+ + ${msg} +
+ % endfor + % endif + + ${self.body()} +
+ + ## Footer + + +
+ + ${h.javascript_link(request.static_url('tailbone:static/themes/falafel/js/tailbone.feedback.js') + '?ver={}'.format(tailbone.__version__))} + + + + +<%def name="title()"> + +<%def name="content_title()"> + ${self.title()} + + +<%def name="header_core()"> + + ${self.core_javascript()} + ${self.extra_javascript()} + ${self.core_styles()} + ${self.extra_styles()} + + ## TODO: should this be elsewhere / more customizable? + % if dform is not Undefined: + <% resources = dform.get_widget_resources() %> + % for path in resources['js']: + ${h.javascript_link(request.static_url(path))} + % endfor + % for path in resources['css']: + ${h.stylesheet_link(request.static_url(path))} + % endfor + % endif + + +<%def name="core_javascript()"> + ${self.jquery()} + + ## Vue.js + ${h.javascript_link('https://unpkg.com/vue')} + + ## Buefy 0.7.3 + ${h.javascript_link('https://unpkg.com/buefy@0.7.3/dist/buefy.min.js')} + + ## ${h.javascript_link(request.static_url('tailbone:static/js/lib/jquery.loadmask.min.js'))} + ## ${h.javascript_link(request.static_url('tailbone:static/js/lib/jquery.ui.timepicker.js'))} + + ## ${h.javascript_link(request.static_url('tailbone:static/js/tailbone.js') + '?ver={}'.format(tailbone.__version__))} + ## ${h.javascript_link(request.static_url('tailbone:static/js/tailbone.feedback.js') + '?ver={}'.format(tailbone.__version__))} + ## ${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.js') + '?ver={}'.format(tailbone.__version__))} + + +<%def name="jquery()"> + + ## jQuery 1.12.4 + ${h.javascript_link('https://code.jquery.com/jquery-1.12.4.min.js')} + + ## jQuery 1.11.4 + ## ${h.javascript_link('https://code.jquery.com/ui/{}/jquery-ui.min.js'.format(request.rattail_config.get('tailbone', 'jquery_ui.version', default='1.11.4')))} + + + +<%def name="extra_javascript()"> + +<%def name="core_styles()"> + + ## Bulma 0.7.4 + ${h.stylesheet_link('https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css')} + + ## Buefy 0.7.3 + ${h.stylesheet_link('https://unpkg.com/buefy@0.7.3/dist/buefy.min.css')} + +## ${self.jquery_theme()} +## ${h.stylesheet_link(request.static_url('tailbone:static/css/jquery.loadmask.css'))} +## ${h.stylesheet_link(request.static_url('tailbone:static/css/jquery.ui.timepicker.css'))} +## ${h.stylesheet_link(request.static_url('tailbone:static/css/jquery.ui.tailbone.css') + '?ver={}'.format(tailbone.__version__))} + + ${h.stylesheet_link(request.static_url('tailbone:static/themes/bobcat/css/base.css') + '?ver={}'.format(tailbone.__version__))} + ${h.stylesheet_link(request.static_url('tailbone:static/themes/falafel/css/layout.css') + '?ver={}'.format(tailbone.__version__))} + ${h.stylesheet_link(request.static_url('tailbone:static/css/grids.css') + '?ver={}'.format(tailbone.__version__))} +## ${h.stylesheet_link(request.static_url('tailbone:static/css/filters.css') + '?ver={}'.format(tailbone.__version__))} + ${h.stylesheet_link(request.static_url('tailbone:static/themes/bobcat/css/forms.css') + '?ver={}'.format(tailbone.__version__))} + ${h.stylesheet_link(request.static_url('tailbone:static/css/diffs.css') + '?ver={}'.format(tailbone.__version__))} + + +<%def name="jquery_theme()"> + ${h.stylesheet_link('https://code.jquery.com/ui/1.11.4/themes/dark-hive/jquery-ui.css')} + + +<%def name="extra_styles()"> + +<%def name="head_tags()"> + +<%def name="wtfield(form, name, **kwargs)"> +
+ +
+ ${form[name](**kwargs)} +
+
+ diff --git a/tailbone/templates/themes/falafel/feedback_dialog.mako b/tailbone/templates/themes/falafel/feedback_dialog.mako new file mode 100644 index 00000000..874ab952 --- /dev/null +++ b/tailbone/templates/themes/falafel/feedback_dialog.mako @@ -0,0 +1,69 @@ +## -*- coding: utf-8; -*- + +<%def name="feedback_dialog()"> + +