2021-02-05 14:50:50 +01:00

1076 lines
38 KiB
HTML

{% macro render_field_with_errors(field) %}
{% set is_required = kwargs['is_required'] if 'is_required' in kwargs else field.flags.required %}
{% set label_text = field.label.text + ' *' if is_required else field.label.text %}
<div class="form-group row {% if field.errors %} has-error{% endif -%}">
{% if 'ri' in kwargs and kwargs['ri'] == 'checkbox' %}
{% else %}
{{ field.label(text=label_text, class="col-sm-2 col-form-label") }}
{% endif %}
<div class="input-group col-sm-10">
{% set field_class = kwargs['class'] if 'class' in kwargs else '' %}
{% set field_class = field_class + ' form-control' %}
{% if field.errors %}
{% set field_class = field_class + ' is-invalid' %}
{% endif %}
{% if 'ri' in kwargs and kwargs['ri'] == 'multicheckbox' %}
<fieldset class="form-group">
{% for choice in field %}
<div class="form-check">
{{ choice(class="form-check-input") }}
{{ choice.label(class="form-check-label") }}
</div>
{% endfor %}
</fieldset>
{% elif 'ri' in kwargs and kwargs['ri'] == 'multicheckbox-inline' %}
<fieldset class="form-group my-auto">
{% for choice in field %}
<div class="form-check form-check-inline">
{{ choice(class="form-check-input") }}
{{ choice.label(class="form-check-label") }}
</div>
{% endfor %}
</fieldset>
{% elif 'ri' in kwargs and kwargs['ri'] == 'checkbox' %}
<div class="form-check">
{{ field(class="form-check-input") }}
{{ field.label(class="form-check-label") }}
</div>
{% else %}
{% if 'class' in kwargs %}
{% set _dummy=kwargs.pop('class') %}
{% endif %}
{{ field(class=field_class, **kwargs)|safe }}
{% endif %}
{% if 'ri' in kwargs %}
{% if kwargs['ri'] == 'rrule' %}
<script type="text/javascript">
$( function() {
$("textarea[name=recurrence_rule]").recurrenceinput({lang:'de', startField: "start", ajaxURL: "{{ url_for('event_rrule') }}", firstDay: 1});
});
</script>
{% endif %}
{% endif %}
<small class="form-text text-muted w-100">
{{ field.description }} {% if is_required %}{{ _('This field is required.') }}{% else %}{{ _('This field is optional.') }}{% endif %}
</small>
{% if field.errors %}
<div class="invalid-feedback d-block">
{% for error in field.errors %}
<div>{{ error }}</div>
{% endfor %}
</div>
{% endif %}
</div>
</div>
{% endmacro %}
{% macro render_field(field) %}
<p>{{ field(class="btn btn-primary", **kwargs)|safe }}</p>
{% endmacro %}
{% macro render_field_errors(field) %}
<p>
{% if field and field.errors %}
<ul>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</p>
{% endmacro %}
{% macro render_event_organizer(organizer) %}
{{ organizer.name }}
{% endmacro %}
{% macro render_location(location) %}
{%- if location.street -%}
{{ location.street }}, {{ location.postalCode }} {{ location.city }}
{%- elif location.postalCode or location.city -%}
{{ location.postalCode }} {{ location.city }}
{%- endif -%}
{% endmacro %}
{% macro render_place(place) %}
{%- if place.location -%}
{{ place.name }}, {{render_location(place.location)}}
{%- else -%}
{{ place.name }}
{%- endif -%}
{% endmacro %}
{% macro render_events_sub_menu() %}
{% endmacro %}
{% macro render_events(events) %}
<div class="table-responsive">
<table class="table table-sm table-bordered table-hover table-striped">
<thead>
<tr>
<th>{{ _('Date') }}</th>
<th>{{ _('Name') }}</th>
<th>{{ _('Host') }}</th>
<th>{{ _('Location') }}</th>
</tr>
</thead>
<tbody>
{% for event in events %}
<tr>
<td>{{ render_event_date(event) }}</td>
<td>
<a href="{{ url_for('event', event_id=event.id) }}">{{ event.name }}</a>
{{ render_event_warning_pills(event) }}
</td>
<td>{{ render_event_organizer(event.organizer) }}</td>
<td>{{ render_place(event.event_place) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="list-group my-4">
<a href="{{ url_for('events') }}" class="list-group-item list-group-item-action list-group-item-primary">
{{ _('Show all events') }}
<i class="fa fa-caret-right"></i>
</a>
</div>
{% endmacro %}
{% macro render_location_card(location, place=None) %}
{% if location %}
<div class="card card-body">
<p>
{{ location.street }}<br />
{{ location.postalCode }} {{ location.city }}
</p>
<p>
<a href="http://www.google.com/maps?q={% if place %}{{ render_place(place) | quote_plus }}{% else %}{{ render_location(location) | quote_plus }}{% endif %}">{{ _('Show on Google Maps') }}</a>
</p>
</div>
{% endif %}
{% endmacro %}
{% macro render_kv_begin() %}
<dl class="row">
{% endmacro %}
{% macro render_kv_end() %}
</dl>
{% endmacro %}
{% macro render_kv_prop(prop, label_key = None) %}
{% if prop %}
<dt class="col-sm-3">{{ _(label_key) }}</dt>
<dd class="col-sm-9">{% if prop|is_list %}{{ prop|join(', ') }}{% else %}{{ prop }}{% endif %}</dd>
{% endif %}
{% endmacro %}
{% macro render_string_prop(prop, icon = None, label_key = None) %}
{% if prop %}
<div>
{% if icon %}<i class="fa fa-fw {{ icon }}" data-toggle="tooltip" title="{{ _(label_key) }}"></i>{% endif %}
{{ prop }}
</div>
{% endif %}
{% endmacro %}
{% macro render_int_prop(prop, icon = None, label_key = None) %}
{% if prop %}
<div>
{% if icon %}<i class="fa fa-fw {{ icon }}" data-toggle="tooltip" title="{{ _(label_key) }}"></i>{% endif %}
{{ prop }}
</div>
{% endif %}
{% endmacro %}
{% macro render_bool_prop(prop, icon, label_key) %}
{% if prop %}
<div>
<i class="fa fa-fw {{ icon }}" data-toggle="tooltip" title="{{ _(label_key) }}"></i>
{{ _(label_key) }}
</div>
{% endif %}
{% endmacro %}
{% macro render_enum_prop(prop, icon, label_key) %}
{% if prop and prop.value > 0 %}
<div>
<i class="fa fa-fw {{ icon }}" data-toggle="tooltip" title="{{ _(label_key) }}"></i>
{{ prop | loc_enum }}
</div>
{% endif %}
{% endmacro %}
{% macro render_range_prop(from, to, icon, label_key) %}
{% if from or to %}
<div>
<i class="fa fa-fw {{ icon }}" data-toggle="tooltip" title="{{ _(label_key) }}"></i>
{{ from if from }} - {{ to if to }}
</div>
{% endif %}
{% endmacro %}
{% macro render_tag_prop(tags) %}
{% if tags %}
<div>
<i class="fa fa-fw fa-tags" data-toggle="tooltip" title="{{ _('Tags') }}"></i>
{{ tags }}
</div>
{% endif %}
{% endmacro %}
{% macro render_link_prop(link) %}
{% if link %}
<div>
<i class="fa fa-fw fa-link" data-toggle="tooltip" title="{{ _('Link') }}"></i>
<a href="{{ link }}" target="_blank" rel="noopener noreferrer">{{ link }}</a>
</div>
{% endif %}
{% endmacro %}
{% macro render_email_prop(email) %}
{% if email %}
<div>
<i class="fa fa-fw fa-envelope" data-toggle="tooltip" title="{{ _('Email') }}"></i>
<a href="mailto:{{ email }}">{{ email }}</a>
</div>
{% endif %}
{% endmacro %}
{% macro render_event_status_pill(event) %}
{% if event.status and event.status != 1 %}
<span class="badge badge-pill badge-warning">{{ event.status | loc_enum }}</span>
{% endif %}
{% endmacro %}
{% macro render_booked_up_pill(event) %}
{% if event.booked_up %}
<span class="badge badge-pill badge-warning">{{ _('Booked up') }}</span>
{% endif %}
{% endmacro %}
{% macro render_event_warning_pills(event) %}
{{ render_event_status_pill(event) }} {{ render_booked_up_pill(event) }}
{% endmacro %}
{% macro render_event_review_status_pill(event) %}
{% if event.review_status %}
<span class="badge badge-pill {% if event.review_status == 2 %}badge-success{% elif event.review_status == 1 %}badge-info{% else %}badge-danger{% endif %}">{{ event.review_status | loc_enum }}</span>
{% endif %}
{% endmacro %}
{% macro render_reference_request_review_status_pill(reference_request) %}
{% if reference_request.review_status %}
<span class="badge badge-pill {% if reference_request.review_status == 1 %}badge-info{% elif reference_request.review_status == 2 %}badge-success{% else %}badge-danger{% endif %}">{{ reference_request.review_status | loc_enum }}</span>
{% endif %}
{% endmacro %}
{% macro render_phone_prop(phone) %}
{% if phone %}
<div>
<i class="fa fa-fw fa-phone" data-toggle="tooltip" title="{{ _('Phone') }}"></i>
<a href="tel:{{ phone }}">{{ phone }}</a>
</div>
{% endif %}
{% endmacro %}
{% macro render_fax_prop(fax) %}
{% if fax %}
<div><i class="fa fa-fw fa-fax" data-toggle="tooltip" title="{{ _('Fax') }}"></i> {{ fax }}</div>
{% endif %}
{% endmacro %}
{% macro render_location_prop(location) %}
{% if location and location.street or location.postalCode or location.city %}
<div>
<i class="fa fa-fw fa-map-marker" data-toggle="tooltip" title="{{ _('Location') }}"></i>
{{ render_location(location) }}
</div>
{% endif %}
{% endmacro %}
{% macro render_img_src(image, size=500) %}
<img src="{{ url_for('image', id=image.id, s=size) }}" class="{{ kwargs['class'] or 'img-fluid' }}" style="{{ kwargs['style'] or 'max-width:100%;' }}" />
{% endmacro %}
{% macro render_image(image, size=500) %}
{% if image %}
{% set img_class = kwargs['class'] if 'class' in kwargs else '' %}
{% set img_style = kwargs['style'] if 'style' in kwargs else '' %}
{% if image.copyright_text %}
<figure class="figure">
{% set img_class = img_class + ' figure-img' %}
{{ render_img_src(image, size, class=img_class, style=img_style) }}
<figcaption class="figure-caption">&copy; {{ image.copyright_text }}</figcaption>
</figure>
{% else %}
{% set img_class = img_class + ' mb-2' %}
{{ render_img_src(image, size, class=img_class, style=img_style) }}
{% endif %}
{% endif %}
{% endmacro %}
{% macro render_logo(image) %}
{{ render_image(image, 120, style="max-width:120px;") }}
{% endmacro %}
{% macro render_event_review_status(event) %}
{{ render_enum_prop(event.review_status, 'fa-certificate', 'Review status') }}
{{ render_enum_prop(event.rejection_resaon, 'fa-search-minus', 'Rejection reason') }}
{% endmacro %}
{% macro render_reference_request_review_status(reference_request) %}
{{ render_enum_prop(reference_request.review_status, 'fa-certificate', 'Review status') }}
{{ render_enum_prop(reference_request.rejection_reason, 'fa-search-minus', 'Rejection reason') }}
{% endmacro %}
{% macro render_audit(tracking_mixing, show_user=False) %}
{% set created_at = tracking_mixing.created_at | datetimeformat('short') %}
{% set updated_at = tracking_mixing.updated_at | datetimeformat('short') %}
{% if show_user %}
{{ _('Created at %(created_at)s by %(created_by)s.', created_at=created_at, created_by=tracking_mixing.created_by.email) }}
{% else %}
{{ _('Created at %(created_at)s.', created_at=created_at) }}
{% endif %}
{% if created_at != updated_at %}
{% if show_user %}
{{ _('Last updated at %(updated_at)s by %(updated_by)s.', updated_at=updated_at, updated_by=tracking_mixing.updated_by.email) }}
{% else %}
{{ _('Last updated at %(updated_at)s.', updated_at=updated_at) }}
{% endif %}
{% endif %}
{% endmacro %}
{% macro render_audit_container(tracking_mixing, show_user=False) %}
<div class="my-4 small">{{ render_audit(tracking_mixing, show_user) }}</div>
{% endmacro %}
{% macro render_event_add_props(event) %}
{{ render_string_prop(event.price_info, 'fa-euro-sign', 'Price info') }}
{{ render_link_prop(event.external_link) }}
{{ render_link_prop(event.ticket_link) }}
{% if event.category %}
<div><i class="fa fa-fw fa-archive" data-toggle="tooltip" title="{{ _('Category') }}"></i> {% for category in event.categories %}{{ category | event_category_name }}{%if not loop.last %}, {% endif %}{% endfor %}</div>
{% endif %}
{{ render_tag_prop(event.tags) }}
{{ render_bool_prop(event.kid_friendly, 'fa-child', 'Kid friendly') }}
{{ render_bool_prop(event.accessible_for_free, 'fa-door-open', 'Accessible for free') }}
{{ render_range_prop(event.age_from, event.age_to, 'fa-people-arrows', 'Typical Age range') }}
{{ render_enum_prop(event.target_group_origin, 'fa-users', 'Target group origin') }}
{{ render_enum_prop(event.attendance_mode, 'fa-mouse-pointer', 'Attendance mode') }}
{{ render_bool_prop(event.registration_required, 'fa-list', 'Registration required') }}
{{ render_bool_prop(event.booked_up, 'fa-square-full', 'Booked up') }}
{{ render_int_prop(event.expected_participants, 'fa-users', 'Expected number of participants') }}
{% endmacro %}
{% macro render_event_props(event, start, end, dates = None, show_rating = False, show_admin_unit = True) %}
<div class="card mb-3">
<div class="card-header">
{{ _('Event') }}
</div>
<div class="card-body">
<h5 class="card-title">{{ event.name }}{{ render_event_warning_pills(event) }}</h5>
{% if dates and dates|length > 1 %}
<div>
<i class="fa fa-fw fas fa-calendar" data-toggle="tooltip" title="{{ _('Date') }}"></i>
{{ start | timeformat('short') }}
{% if end %}- {{ end | timeformat('short') }}{% endif %}
| <a href="#event-dates">{{ _('%(count)d event dates', count=dates|length) }}</a>
</div>
{% else %}
<div>
<i class="fa fa-fw fa-calendar" data-toggle="tooltip" title="{{ _('Date') }}"></i>
{{ start | datetimeformat('short') }}
{% if end %}- {{ end | datetimeformat('short') }}{% endif %}
</div>
{% endif %}
{{ render_enum_prop(event.status, 'fa-info-circle', 'Status') }}
{% if event.previous_start_date %}
<div><i class="fa fa-fw fa-calendar-times" data-toggle="tooltip" title="{{ _('Previous start date') }}"></i> {{ event.previous_start_date | datetimeformat('short') }}</div>
{% endif %}
{% if show_rating and event.rating %}
{{ render_string_prop("%d/10" % (event.rating/10), 'fa-adjust', 'Rating') }}
{% endif %}
{% if event.photo_id %}
<div class="my-4">{{ render_image(event.photo, 700) }}</div>
{% endif %}
<div class="my-4">{{ event.description }}</div>
<div class="mt-4">
{{ render_event_add_props(event) }}
</div>
</div>
<div class="card-footer small">
{{ render_audit(event, show_rating) }}
</div>
</div>
<div class="card mb-3">
<div class="card-header">
{{ _('Place') }}
</div>
<div class="card-body">
{% if event.event_place %}
<h5 class="card-title">{{ event.event_place.name }}</h5>
{% if event.event_place.photo_id %}
<div class="my-4">{{ render_image(event.event_place.photo, 300) }}</div>
{% endif %}
{% if event.event_place.description %}
<div class="my-4">{{ event.event_place.description }}</div>
{% endif %}
<div class="my-4">
{{ render_link_prop(event.event_place.url) }}
{{ render_location_prop(event.event_place.location) }}
</div>
<p>
<a href="http://www.google.com/maps?q={{ render_place(event.event_place) | quote_plus }}" class="btn btn-secondary" target="_blank" rel="noopener noreferrer">{{ _('Show directions') }}</a>
</p>
{% endif %}
</div>
</div>
{% if event.organizer %}
<div class="card mb-3">
<div class="card-header">
{{ _('Organizer') }}
</div>
<div class="card-body">
<h5 class="card-title">{{ render_string_prop(event.organizer.name) }}</h5>
{% if event.organizer.logo_id %}
<div class="my-4">{{ render_logo(event.organizer.logo) }}</div>
{% endif %}
{{ render_link_prop(event.organizer.url) }}
{{ render_email_prop(event.organizer.email) }}
{{ render_phone_prop(event.organizer.phone) }}
{{ render_fax_prop(event.organizer.fax) }}
</div>
</div>
{% endif %}
{% if show_admin_unit %}
<div class="card mb-3">
<div class="card-header">
{{ _('Admin unit') }}
</div>
<div class="card-body">
<h5 class="card-title">{{ event.admin_unit.name }}</h5>
{% if event.admin_unit.logo_id %}
<div class="my-4">{{ render_logo(event.admin_unit.logo) }}</div>
{% endif %}
<div class="my-4">
{{ render_link_prop(event.admin_unit.url) }}
{{ render_email_prop(event.admin_unit.email) }}
{{ render_phone_prop(event.admin_unit.phone) }}
{{ render_fax_prop(event.admin_unit.fax) }}
{{ render_location_prop(event.admin_unit.location) }}
</div>
</div>
</div>
{% endif %}
{% endmacro %}
{% macro render_google_place_autocomplete_header(location_only = False) %}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key={{ "dev" | env_override('GOOGLE_MAPS_API_KEY') }}&libraries=places"></script>
<script>
function initialize() {
var input = document.getElementById('location_search');
var autocomplete = new google.maps.places.Autocomplete(input);
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
var street_number = "";
var route = "";
var city = "";
for (var i = 0; i < place.address_components.length; i++) {
var component = place.address_components[i]
var addressType = component.types[0];
var val = component.long_name
if (addressType == 'street_number') {
street_number = val;
} else if (addressType == 'route') {
route = val;
} else if (addressType == 'locality') {
city = val;
} else if (addressType == 'administrative_area_level_1') {
$('#location-state').val(val);
} else if (addressType == 'postal_code') {
$('#location-postalCode').val(val);
}
}
{% if not location_only %}
$('#name').val(place.name);
if (place.website) {
$('#url').val(place.website);
}
{% endif %}
$('#location-street').val([route, street_number].join(' '));
$('#location-city').val(city);
$('#location-latitude').val(place.geometry.location.lat());
$('#location-longitude').val(place.geometry.location.lng());
$('#location_search').val('');
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
{% endmacro %}
{% macro render_google_place_autocomplete_field() %}
<div class="form-group row">
<div class="input-group col-sm-12">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fab fa-google"></i></span>
</div>
<input id="location_search" type="text" class="form-control" placeholder="{{ _('Search location on Google') }}" autocomplete="on" runat="server" />
</div>
</div>
{% endmacro %}
{% macro render_google_filter_autocomplete_header() %}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key={{ "dev" | env_override('GOOGLE_MAPS_API_KEY') }}&libraries=places"></script>
<script>
function initialize() {
var input = document.getElementById('location');
var autocomplete = new google.maps.places.Autocomplete(input);
google.maps.event.addListener(autocomplete, 'place_changed', function () {
var place = autocomplete.getPlace();
$('#coordinate').val('' + place.geometry.location.lat() + ',' + place.geometry.location.lng());
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
{% endmacro %}
{% macro render_event_date(event) %}
{{ event.start | datetimeformat('short') }}
{% if event.recurrence_rule %}
<i class="fas fa-history"></i>
{% endif %}
{% endmacro %}
{% macro render_pagination(pagination) %}
{% if 'prev_url' in pagination or 'next_url' in pagination %}
<nav aria-label="Page navigation">
<ul class="pagination">
{% if pagination['prev_url'] %}
<li class="page-item"> <a class="page-link" href="{{ pagination['prev_url'] }}">{{ _('Previous') }}</a></li>
{% else %}
<li class="page-item"><a class="page-link btn disabled" href="#">{{ _('Previous') }}</a></li>
{% endif %}
{% if pagination['next_url'] %}
<li class="page-item"> <a class="page-link" href="{{ pagination['next_url'] }}">{{ _('Next') }}</a></li>
{% else %}
<li class="page-item"><a class="page-link btn disabled" href="#">{{ _('Next') }}</a></li>
{% endif %}
</ul>
</nav>
{% endif %}
{% endmacro %}
{% macro render_roles(roles) %}
{% if roles %}
{% for role in roles %}{{ _(role.title) }}{%if not loop.last %}, {% endif %}{% endfor %}
{% endif %}
{% endmacro %}
{% macro render_email_button(url, title) %}
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a href="{{ url }}" target="_blank" rel="noopener noreferrer">{{ title }}</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
{% endmacro %}
{% macro render_radio_buttons(field) %}
{% for subfield in field %}
<div class="form-check form-check-inline">
<td>{{ subfield(class="form-check-input") }}</td>
<td>{{ subfield.label(class="form-check-label") }}</td>
</div>
{% endfor %}
{% endmacro %}
{% macro render_event_dates_date_field(from_field, to_field) %}
<div class="form-group row">
<label class="col-sm-2 col-form-label">{{ _('Date') }}</label>
<div class="col-sm-5 mb-1">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">{{ from_field.label.text }}</span>
</div>
{{ from_field(class="form-control datepicker")|safe }}
</div>
</div>
<div class="col-sm-5">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">{{ to_field.label.text }}</span>
</div>
{{ to_field(class="form-control datepicker")|safe }}
</div>
</div>
</div>
{% endmacro %}
{% macro render_event_dates_location_field(location_field, distance_field) %}
{% if location_field %}
<div class="form-group row">
<label for="location" class="col-sm-2 col-form-label">{{ _('Radius') }}</label>
<div class="col-sm-7 mb-1">
<div class="input-group">
{{ location_field(class="form-control", placeholder='Ort', autocomplete="off")|safe }}
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="clear_location_btn">
<i class="fa fa-times"></i>
</button>
<button class="btn btn-outline-primary" type="button" id="geolocation_btn">
<i class="fa fa-location-arrow"></i>
</button>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">{{ distance_field.label.text }}</span>
</div>
{{ distance_field(class="form-control")|safe }}
</div>
</div>
</div>
{% endif %}
{% endmacro %}
{% macro render_event_dates_filter_form(form) %}
<form action="" id="filter_form" class="form" method="GET" autocomplete="off">
{{ form.hidden_tag() }}
{% if form.keyword %}
{{ render_field_with_errors(form.keyword) }}
{% endif %}
{% if form.category_id %}
{{ render_field_with_errors(form.category_id) }}
{% endif %}
{% if form.organizer_id %}
{{ render_field_with_errors(form.organizer_id) }}
{% endif %}
{{ render_event_dates_date_field(form.date_from, form.date_to) }}
{% if form.weekday and form.weekday.choices|length > 0 %}
{{ render_field_with_errors(form.weekday, ri="multicheckbox") }}
{% endif %}
{{ render_event_dates_location_field(form.location, form.distance) }}
{{ render_field(form.submit) }}
</form>
{% endmacro %}
{% macro render_cropper_code(field_id = "photo", min_width=320, min_height=160) %}
var field_id = "#{{ field_id }}-image_base64";
var inputImage = document.getElementById('photo-image_file');
var Cropper = window.Cropper;
var URL = window.URL || window.webkitURL;
var image = document.getElementById('photo-image');
var cropper = null;
var crop_data = null;
var minCroppedWidth = {{ min_width }};
var minCroppedHeight = {{ min_height }};
var uploadedImageURL;
var photo_modal = $('#photo_modal');
if (URL) {
inputImage.onchange = function () {
var files = this.files;
var file;
if (files && files.length) {
file = files[0];
if (/^image\/\w+/.test(file.type)) {
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
}
image.src = uploadedImageURL = URL.createObjectURL(file);
inputImage.value = null;
crop_data = null;
photo_modal.modal();
} else {
window.alert('Please choose an image file.');
}
}
};
photo_modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
viewMode: 1,
autoCropArea: 1.0,
data: crop_data,
ready() {
var image_data = cropper.getImageData();
if (image_data.naturalWidth < minCroppedWidth || image_data.naturalHeight < minCroppedHeight) {
window.alert('Die Auflösung ist zu gering. Mindestens ' + minCroppedWidth + 'x' + minCroppedHeight + 'px.');
photo_modal.modal('hide');
}
},
crop: function (event) {
var width = event.detail.width;
var height = event.detail.height;
if (width < minCroppedWidth || height < minCroppedHeight) {
cropper.setData({
width: Math.max(minCroppedWidth, width),
height: Math.max(minCroppedHeight, height),
});
}
}
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
if ($('#photo_preview').attr("src")) {
image.src = uploadedImageURL = $('#photo_preview').attr("src");
} else {
$('.show-if-photo-exists').hide();
}
$('#photo-edit-btn').click(function(e){
e.preventDefault();
photo_modal.modal();
});
$('#photo-delete-btn').click(function(e){
e.preventDefault();
$(field_id).val('');
$('#photo_preview').attr("src", '');
$('.show-if-photo-exists').hide();
});
$('#photo-zoom-in').click(function(e){
e.preventDefault();
cropper.zoom(0.1);
});
$('#photo-zoom-out').click(function(e){
e.preventDefault();
cropper.zoom(-0.1);
});
$('#photo-rotate-left').click(function(e){
e.preventDefault();
cropper.rotate(-90);
});
$('#photo-rotate-right').click(function(e){
e.preventDefault();
cropper.rotate(90);
});
$('#photo-save-btn').click(function(e){
e.preventDefault();
photo_modal.modal('hide');
if (cropper) {
var canvas = cropper.getCroppedCanvas({
maxWidth: 1200,
maxHeight: 1200,
fillColor: '#eee'
});
var data_url = canvas.toDataURL();
crop_data = cropper.getData();
$(field_id).val(data_url);
$('#photo_preview').attr("src", data_url);
$('.show-if-photo-exists').show();
}
});
} else {
inputImage.disabled = true;
inputImage.parentNode.className += ' disabled';
}
{% endmacro %}
{% macro render_cropper_script(field_id = "photo", min_width=320, min_height=160) %}
<script>
$( function() {
{{ render_cropper_code(field_id, min_width, min_height) }}
});
</script>
{% endmacro %}
{% macro render_cropper_block(field_id = "photo", min_width=320, min_height=160) %}
{{ render_cropper_header() }}
{{ render_cropper_script(field_id, min_width, min_height) }}
{% endmacro %}
{% macro render_cropper_logo_block() %}
{{ render_cropper_block("logo", 100, 100) }}
{% endmacro %}
{% macro render_crop_image_form(form_field) %}
{{ form_field.hidden_tag() }}
<div class="card card-body mb-3 p-3">
<div id="photo_modal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ _('Edit image') }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div style="height: 40vh;">
<img class="w-100" id="photo-image" />
</div>
<div class="my-3">
<div class="btn-group">
<button id="photo-zoom-in" type="button" class="btn btn-outline-secondary"><i class="fa fa-search-plus"></i></button>
<button id="photo-zoom-out" type="button" class="btn btn-outline-secondary"><i class="fa fa-search-minus"></i></button>
</div>
<div class="btn-group">
<button id="photo-rotate-left" type="button" class="btn btn-outline-secondary"><i class="fa fa-undo-alt"></i></button>
<button id="photo-rotate-right" type="button" class="btn btn-outline-secondary"><i class="fa fa-redo-alt"></i></button>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ _('Close') }}</button>
<button type="button" class="btn btn-primary" id="photo-save-btn">{{ _('Okay') }}</button>
</div>
</div>
</div>
</div>
<div class="mb-1 show-if-photo-exists"><img id="photo_preview" style="max-height: 20vh;" {% if form_field.image_base64.data %}src="{{ form_field.image_base64.data }}"{% endif %} /></div>
<div class="py-1">
<label class="btn btn-secondary mb-0" for="photo-image_file" title="{{ _('Choose image file') }}">
<input type="file" class="sr-only" id="photo-image_file" name="photo" accept="image/*" />
<span>{{ _('Choose image file') }}&hellip;</span>
</label>
<button id="photo-edit-btn" class="btn btn-outline-secondary show-if-photo-exists"><i class="fa fa-edit"></i></button>
<button id="photo-delete-btn" class="btn btn-outline-secondary show-if-photo-exists"><i class="fa fa-trash"></i></button>
</div>
</div>
{{ render_field_with_errors(form_field.copyright_text) }}
{% endmacro %}
{% macro render_crop_image_form_section(form_field) %}
<div class="card mb-4">
<div class="card-header">
{{ form_field.label() }}
</div>
<div class="card-body">
{{ render_crop_image_form(form_field) }}
{% if form_field.description %}
<small class="form-text text-muted w-100">
{{ form_field.description }}
</small>
{% endif %}
</div>
</div>
{% endmacro %}
{% macro render_base_image_form(form_field) %}
{{ form_field.hidden_tag() }}
{% if form_field.object_data and form_field.object_data.id %}
<div>
<a href="{{ url_for('image', id=form_field.object_data.id) }}" target="_blank" rel="noopener noreferrer"><img src="{{ url_for('image', id=form_field.object_data.id) }}" class="img-fluid" style="max-width:5rem;" /></a>
</div>
{{ render_field_with_errors(form_field.delete_flag, style="width: fit-content; flex: initial;") }}
{% endif %}
{{ render_field_with_errors(form_field.image_file) }}
{{ render_field_with_errors(form_field.copyright_text) }}
{% endmacro %}
{% macro render_base_image_form_section(form_field) %}
<div class="card mb-4">
<div class="card-header">
{{ form_field.label() }}
</div>
<div class="card-body">
{{ render_base_image_form(form_field) }}
</div>
</div>
{% endmacro %}
{% macro render_event_menu(user_rights, event) %}
<div class="dropdown my-4">
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ _('Actions') }}
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
{% if user_rights['can_update_event'] %}
<a class="dropdown-item" href="{{ url_for('event_update', event_id=event.id) }}"><i class="fa fa-edit"></i> {{ _('Edit event') }}</a>
<a class="dropdown-item" href="{{ url_for('event_delete', event_id=event.id) }}"><i class="fa fa-trash"></i> {{ _('Delete event') }}&hellip;</a>
{% endif %}
<a class="dropdown-item" href="{{ url_for('event_actions', event_id=event.id) }}">{{ _('More') }}&hellip;</a>
</div>
</div>
{% endmacro %}
{% macro render_jquery_steps_header() %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-steps/1.1.0/jquery.steps.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.2/jquery.validate.min.js" integrity="sha512-UdIMMlVx0HEynClOIFSyOrPggomfhBKJE28LKl8yR3ghkgugPnG6iLfRfHwushZl1MOPSY6TsuBDGPK2X4zYKg==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.2/additional-methods.min.js" integrity="sha512-6Uv+497AWTmj/6V14BsQioPrm3kgwmK9HYIyWP+vClykX52b0zrDGP7lajZoIY1nNlX4oQuh7zsGjmF7D0VZYA==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.2/localization/messages_de.min.js" integrity="sha512-CZoLR7uTljYchtaY9SbWetTDxZ7bW3h6YALF4orf6k+WTvZhr4zu+a9XqhHkK+zsKbQL5HNXTNrd21TE3M6eUg==" crossorigin="anonymous"></script>
{% endmacro %}
{% macro render_cropper_header() %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.9/cropper.js" integrity="sha512-oqBsjjSHWqkDx4UKoU+5IUZN2nW2qDp2GFSKw9+mcFm+ZywqfBKp79nfWmGPco2wzTWuE46XpjtCjZ9tFmI12g==" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.9/cropper.css" integrity="sha512-949FvIQOibfhLTgmNws4F3DVlYz3FmCRRhJznR22hx76SKkcpZiVV5Kwo0iwK9L6BFuY+6mpdqB2+vDIGVuyHg==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cropper/1.0.1/jquery-cropper.js" integrity="sha512-7H4tikIFoyAdYD31w/uNYvvAUL6gyunWXLwTQ7ZXkyjD+brw+PfJpLxFkANnbkKnSJzU89YpnF3fJKbpvV+QYg==" crossorigin="anonymous"></script>
{% endmacro %}
{% macro render_event_suggestion(event_suggestion, hide_review_status=False) %}
<div class="card mb-3">
<div class="card-header">
{{ _('Event suggestion') }}
</div>
<div class="card-body">
{% if event_suggestion.photo_id %}
<div class="">
{{ render_image(event_suggestion.photo, class='rounded', style='object-fit: cover; height: 20vh;') }}
</div>
{% elif event_suggestion.photo and event_suggestion.photo.image_base64 %}
<div class="mb-1"><img class="rounded" style="object-fit: cover; height: 20vh;" src="{{ event_suggestion.photo.image_base64 }}" /></div>
{% endif %}
<div class="text-highlight text-uppercase font-weight-bold">{{ event_suggestion.start | dateformat('full') }} um {{ event_suggestion.start | timeformat('short') }}</div>
<div class="font-weight-bold" style="font-size: 1.8rem;">{{ event_suggestion.name }}</div>
<div class="text-muted">{{ event_suggestion.event_place.name or event_suggestion.event_place_text }}</div>
<div class="mt-3"><i class="fa fa-fw fa-sitemap"></i> {{ event_suggestion.organizer.name or event_suggestion.organizer_text }}</div>
{{ render_link_prop(event_suggestion.external_link) }}
<div class="my-2">{{ event_suggestion.description }}</div>
<div class="mt-4">
{{ render_event_add_props(event_suggestion) }}
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
{{ _('Contact') }}
</div>
<div class="card-body">
{{ render_string_prop(event_suggestion.contact_name, 'fa-user') }}
{{ render_email_prop(event_suggestion.contact_email) }}
{{ render_phone_prop(event_suggestion.contact_phone) }}
</div>
</div>
{% if not hide_review_status %}
<div class="card mb-3">
<div class="card-header">
{{ _('Review status') }}
</div>
<div class="card-body">
{{ render_event_review_status(event_suggestion) }}
</div>
</div>
{% endif %}
{% endmacro %}
{% macro render_widget_styles(styles) %}
<style>
body {
{% if 'background' in styles %}
background-color: {{ styles['background'] }};
{% endif %}
{% if 'font' in styles %}
font-family: {{ styles['font'] }};
{% endif %}
}
{% if 'primary' in styles %}
.btn-primary,
.btn-primary:hover,
.btn-primary:active,
.btn-primary:not(:disabled):not(.disabled):active,
.btn-primary:focus {
background-color: {{ styles['primary'] }};
border-color: {{ styles['primary'] }};
}
{% endif %}
{% if 'link' in styles %}
.card-title, .page-link, .page-link:hover, a, a:hover {
color: {{ styles['link'] }};
}
{% endif %}
{% if 'primary' in styles %}
.wizard > .steps .current a,
.wizard > .steps .current a:hover,
.wizard > .steps .current a:active,
.wizard > .steps .current a,
.wizard > .steps .current a:hover,
.wizard > .steps .current a:active,
.wizard > .steps .done a,
.wizard > .steps .done a:hover,
.wizard > .steps .done a:active,
.wizard > .actions a,
.wizard > .actions a:hover,
.wizard > .actions a:active
{
background-color: {{ styles['primary'] }};
}
{% endif %}
</style>
{% endmacro %}