mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 08:09:37 +00:00
Merge pull request #212 from DanielGrams/issue/211
Optimize event suggestion input #211
This commit is contained in:
commit
ebf1a87371
@ -53,6 +53,9 @@ class CreateEventSuggestionForm(SharedEventForm):
|
||||
"Choose where the event takes place. If the venue is not yet in the list, just enter it."
|
||||
),
|
||||
)
|
||||
event_place_id_suffix = StringField(
|
||||
validators=[Optional()],
|
||||
)
|
||||
organizer_id = TagSelectField(
|
||||
lazy_gettext("Organizer"),
|
||||
validators=[DataRequired()],
|
||||
@ -60,6 +63,9 @@ class CreateEventSuggestionForm(SharedEventForm):
|
||||
"Select the organizer. If the organizer is not yet on the list, just enter it."
|
||||
),
|
||||
)
|
||||
organizer_id_suffix = StringField(
|
||||
validators=[Optional()],
|
||||
)
|
||||
|
||||
category_ids = SelectMultipleField(
|
||||
lazy_gettext("Categories"),
|
||||
@ -82,9 +88,19 @@ class CreateEventSuggestionForm(SharedEventForm):
|
||||
if name == "event_place_id" and self.event_place_id.is_free_text():
|
||||
obj.event_place_text = self.event_place_id.data
|
||||
obj.event_place_id = None
|
||||
|
||||
if self.event_place_id_suffix.data:
|
||||
obj.event_place_text = (
|
||||
obj.event_place_text + ", " + self.event_place_id_suffix.data
|
||||
)
|
||||
elif name == "organizer_id" and self.organizer_id.is_free_text():
|
||||
obj.organizer_text = self.organizer_id.data
|
||||
obj.organizer_id = None
|
||||
|
||||
if self.organizer_id_suffix.data:
|
||||
obj.organizer_text = (
|
||||
obj.organizer_text + ", " + self.organizer_id_suffix.data
|
||||
)
|
||||
elif name == "target_group_origin":
|
||||
obj.target_group_origin = EventTargetGroupOrigin(
|
||||
self.target_group_origin.data
|
||||
|
||||
@ -98,20 +98,30 @@ jQuery.tools.recurrenceinput.localize('de', {
|
||||
}
|
||||
});
|
||||
|
||||
function set_min_date(picker, data_range_to_attr) {
|
||||
function set_date_bounds(picker) {
|
||||
var data_range_to_attr = picker.attr('data-range-to');
|
||||
|
||||
if (data_range_to_attr) {
|
||||
$(data_range_to_attr + '-user').datepicker("option", "minDate", picker.datepicker("getDate"));
|
||||
from_date = picker.datepicker("getDate");
|
||||
from_moment = moment(from_date);
|
||||
$(data_range_to_attr + '-user').datepicker("option", "minDate", from_date);
|
||||
|
||||
var data_range_max_attr = picker.attr('data-range-max-days');
|
||||
if (data_range_max_attr) {
|
||||
from_moment.add(data_range_max_attr, 'days');
|
||||
$(data_range_to_attr + '-user').datepicker("option", "maxDate", from_moment.toDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function set_picker_date(picker, date, data_range_to_attr, timeout = -1) {
|
||||
function set_picker_date(picker, date, timeout = -1) {
|
||||
picker.datepicker("setDate", date);
|
||||
|
||||
if (timeout < 0) {
|
||||
set_min_date(picker, data_range_to_attr);
|
||||
set_date_bounds(picker);
|
||||
} else {
|
||||
window.setTimeout(function() {
|
||||
set_min_date(picker, data_range_to_attr);
|
||||
set_date_bounds(picker);
|
||||
}, timeout);
|
||||
}
|
||||
}
|
||||
@ -138,17 +148,15 @@ function start_datepicker(input) {
|
||||
hidden_field.data('picker', picker);
|
||||
hidden_field.hide();
|
||||
|
||||
var data_range_to_attr = hidden_field.attr('data-range-to');
|
||||
|
||||
var hidden_value = hidden_field.val();
|
||||
if (hidden_value) {
|
||||
set_picker_date(picker, moment(hidden_value).toDate(), data_range_to_attr, 100)
|
||||
set_picker_date(picker, moment(hidden_value).toDate(), 100)
|
||||
}
|
||||
|
||||
hidden_field.after(user_field);
|
||||
|
||||
$("#" + hidden_field_id + "-clear-button").click(function() {
|
||||
set_picker_date(picker, null, data_range_to_attr)
|
||||
set_picker_date(picker, null)
|
||||
$("#" + hidden_field_id + "-hour").val("00");
|
||||
$("#" + hidden_field_id + "-minute").val("00");
|
||||
});
|
||||
@ -163,16 +171,16 @@ function start_datepicker(input) {
|
||||
if (!hidden_moment.isSame(existing_moment)) {
|
||||
picker.datepicker("setDate", hidden_moment.toDate());
|
||||
}
|
||||
set_min_date(picker, data_range_to_attr);
|
||||
set_date_bounds(picker);
|
||||
} else if (existing_date != null) {
|
||||
set_picker_date(picker, null, data_range_to_attr)
|
||||
set_picker_date(picker, null)
|
||||
}
|
||||
});
|
||||
|
||||
user_field.change(function() {
|
||||
var user_value = user_field.val();
|
||||
if (!user_value) {
|
||||
set_picker_date(picker, null, data_range_to_attr)
|
||||
set_picker_date(picker, null)
|
||||
}
|
||||
});
|
||||
|
||||
@ -200,7 +208,7 @@ function handle_request_success(result_id = '#result_container', spinner_id = '#
|
||||
$( function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
$('.autocomplete').select2({width: '100%'});
|
||||
$('.autocomplete-tags').select2({width: '100%', tags: true});
|
||||
|
||||
$('.datepicker').each(function (index, element){
|
||||
start_datepicker($(element));
|
||||
});
|
||||
|
||||
@ -1143,6 +1143,45 @@ if (URL) {
|
||||
<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>
|
||||
<script>
|
||||
function get_moment_with_time(field_id) {
|
||||
return moment($(field_id).val()).add($(field_id + "-hour").val(), "hour").add($(field_id + "-minute").val(), "minute");
|
||||
}
|
||||
|
||||
jQuery.validator.addMethod("dateRange", function(value, element, params) {
|
||||
var start_id = params[0];
|
||||
var end_id = params[1];
|
||||
|
||||
var start_val = $(start_id).val();
|
||||
var end_val = $(end_id).val();
|
||||
|
||||
if (start_val == '' || end_val == '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
var start = get_moment_with_time(start_id);
|
||||
var end = get_moment_with_time(end_id);
|
||||
return end >= start;
|
||||
}, jQuery.validator.format("{{ _('The start must be before the end.') }}"));
|
||||
|
||||
jQuery.validator.addMethod("dateRangeDay", function(value, element, params) {
|
||||
var start_id = params[0];
|
||||
var end_id = params[1];
|
||||
|
||||
var start_val = $(start_id).val();
|
||||
var end_val = $(end_id).val();
|
||||
|
||||
if (start_val == '' || end_val == '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
var start = get_moment_with_time(start_id);
|
||||
var end = get_moment_with_time(end_id);
|
||||
var max = start.add(1, 'day');
|
||||
return end <= max;
|
||||
}, jQuery.validator.format("{{ _('An event can last a maximum of 24 hours.') }}"));
|
||||
|
||||
</script>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_cropper_header() %}
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
{%- with messages = get_flashed_messages(with_categories=true) -%}
|
||||
<!-- Categories: success (green), info (blue), warning (yellow), danger (red) -->
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="alert alert-{{ category }} alert-dismissible" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<!-- <strong>Title</strong> --> {{ message }}
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
@ -73,7 +73,7 @@ $( function() {
|
||||
{{ _('Event date') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ render_field_with_errors(form.start, **{"data-range-to":"#end"}) }}
|
||||
{{ render_field_with_errors(form.start, **{"data-range-to":"#end", "data-range-max-days": "1"}) }}
|
||||
{{ render_field_with_errors(form.end) }}
|
||||
{{ render_field_with_errors(form.recurrence_rule, ri="rrule") }}
|
||||
</div>
|
||||
|
||||
@ -59,7 +59,7 @@
|
||||
{{ _('Event date') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ render_field_with_errors(form.start, **{"data-range-to":"#end"}) }}
|
||||
{{ render_field_with_errors(form.start, **{"data-range-to":"#end", "data-range-max-days": "1"}) }}
|
||||
{{ render_field_with_errors(form.end) }}
|
||||
{{ render_field_with_errors(form.recurrence_rule, ri="rrule") }}
|
||||
</div>
|
||||
|
||||
@ -59,6 +59,12 @@
|
||||
},
|
||||
contact_phone: {
|
||||
require_from_group: [1, ".contact_method_group"]
|
||||
},
|
||||
start: {
|
||||
dateRange: ["#start", "#end"]
|
||||
},
|
||||
end: {
|
||||
dateRangeDay: ["#start", "#end"]
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -74,7 +80,6 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
//form.validate().settings.ignore = ":disabled,:hidden:not(.datepicker)";
|
||||
form.validate().settings.ignore = ":disabled,:hidden";
|
||||
var is_valid = form.valid();
|
||||
|
||||
@ -96,6 +101,34 @@
|
||||
|
||||
{{ render_cropper_code() }}
|
||||
|
||||
$('#event_place_id').select2({width: '100%', tags: true, selectOnClose: true})
|
||||
.on('select2:select', function (e) {
|
||||
var item = $('#event_place_id').select2('data')[0];
|
||||
var needs_suffix = item.id != '' && item.id == item.text;
|
||||
|
||||
if (needs_suffix) {
|
||||
var input = $($.parseHTML('<input type="text" id="event_place_id_suffix" name="event_place_id_suffix" class="form-control mt-2" placeholder="Adresse" />'));
|
||||
$('#event_place_id').siblings('.select2').after(input);
|
||||
$('#event_place_id_suffix').focus();
|
||||
} else {
|
||||
$('#event_place_id_suffix').remove();
|
||||
}
|
||||
});
|
||||
|
||||
$('#organizer_id').select2({width: '100%', tags: true, selectOnClose: true})
|
||||
.on('select2:select', function (e) {
|
||||
var item = $('#organizer_id').select2('data')[0];
|
||||
var needs_suffix = item.id != '' && item.id == item.text;
|
||||
|
||||
if (needs_suffix) {
|
||||
var input = $($.parseHTML('<input type="text" id="organizer_id_suffix" name="organizer_id_suffix" class="form-control mt-2" placeholder="Adresse" />'));
|
||||
$('#organizer_id').siblings('.select2').after(input);
|
||||
$('#organizer_id_suffix').focus();
|
||||
} else {
|
||||
$('#organizer_id_suffix').remove();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -178,9 +211,9 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ render_field_with_errors(form.name) }}
|
||||
{{ render_field_with_errors(form.event_place_id, class="autocomplete-tags w-100") }}
|
||||
{{ render_field_with_errors(form.organizer_id, class="autocomplete-tags w-100") }}
|
||||
{{ render_field_with_errors(form.start, **{"data-range-to":"#end"}) }}
|
||||
{{ render_field_with_errors(form.event_place_id, class="w-100") }}
|
||||
{{ render_field_with_errors(form.organizer_id, class="w-100") }}
|
||||
{{ render_field_with_errors(form.start, **{"data-range-to":"#end", "data-range-max-days": "1"}) }}
|
||||
{{ render_field_with_errors(form.end) }}
|
||||
{{ render_field_with_errors(form.recurrence_rule, ri="rrule") }}
|
||||
|
||||
|
||||
@ -1,2 +1,6 @@
|
||||
{% from "_macros.html" import render_event_suggestion %}
|
||||
{{ render_event_suggestion(event_suggestion, True) }}
|
||||
{% include "_messages.html" %}
|
||||
|
||||
{% if event_suggestion %}
|
||||
{{ render_event_suggestion(event_suggestion, True) }}
|
||||
{% endif %}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import json
|
||||
|
||||
from flask import abort, flash, redirect, render_template, request, url_for
|
||||
from flask import flash, redirect, render_template, request, url_for
|
||||
from flask_babelex import gettext
|
||||
from flask_security import current_user
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
@ -122,12 +122,11 @@ def event_suggestion_create_for_admin_unit(au_short_name):
|
||||
).first_or_404()
|
||||
|
||||
form = CreateEventSuggestionForm()
|
||||
form.organizer_id.choices = [
|
||||
(o.id, o.name)
|
||||
for o in EventOrganizer.query.filter(
|
||||
EventOrganizer.admin_unit_id == admin_unit.id
|
||||
).order_by(func.lower(EventOrganizer.name))
|
||||
]
|
||||
|
||||
organizers = EventOrganizer.query.filter(
|
||||
EventOrganizer.admin_unit_id == admin_unit.id
|
||||
).order_by(func.lower(EventOrganizer.name))
|
||||
form.organizer_id.choices = [(o.id, o.name) for o in organizers]
|
||||
|
||||
places = get_event_places(admin_unit.id)
|
||||
form.event_place_id.choices = [(p.id, p.name) for p in places]
|
||||
@ -144,6 +143,13 @@ def event_suggestion_create_for_admin_unit(au_short_name):
|
||||
event_suggestion.review_status = EventReviewStatus.inbox
|
||||
|
||||
if "preview" in request.args:
|
||||
event_suggestion.admin_unit = admin_unit
|
||||
event_suggestion.organizer = next(
|
||||
(o for o in organizers if o.id == event_suggestion.organizer_id), None
|
||||
)
|
||||
event_suggestion.event_place = next(
|
||||
(p for p in places if p.id == event_suggestion.event_place_id), None
|
||||
)
|
||||
return render_template(
|
||||
"widget/event_suggestion/create_preview.html",
|
||||
admin_unit=admin_unit,
|
||||
@ -177,10 +183,14 @@ def event_suggestion_create_for_admin_unit(au_short_name):
|
||||
db.session.rollback()
|
||||
flash(handleSqlError(e), "danger")
|
||||
else:
|
||||
if "preview" in request.args:
|
||||
abort(406)
|
||||
flash_errors(form)
|
||||
|
||||
if "preview" in request.args:
|
||||
return render_template(
|
||||
"widget/event_suggestion/create_preview.html",
|
||||
admin_unit=admin_unit,
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"widget/event_suggestion/create.html",
|
||||
form=form,
|
||||
|
||||
@ -87,9 +87,18 @@ def get_create_data():
|
||||
|
||||
@pytest.mark.parametrize("db_error", [True, False])
|
||||
@pytest.mark.parametrize("free_text", [True, False])
|
||||
@pytest.mark.parametrize("free_text_suffix", [True, False])
|
||||
@pytest.mark.parametrize("missing_preview_field", [True, False])
|
||||
def test_event_suggestion_create_for_admin_unit(
|
||||
client, app, seeder, utils, mocker, db_error, free_text, missing_preview_field
|
||||
client,
|
||||
app,
|
||||
seeder,
|
||||
utils,
|
||||
mocker,
|
||||
db_error,
|
||||
free_text,
|
||||
free_text_suffix,
|
||||
missing_preview_field,
|
||||
):
|
||||
user_id = seeder.create_user()
|
||||
admin_unit_id = seeder.create_admin_unit(user_id, "Meine Crew")
|
||||
@ -105,6 +114,10 @@ def test_event_suggestion_create_for_admin_unit(
|
||||
data["event_place_id"] = seeder.upsert_default_event_place(admin_unit_id)
|
||||
data["organizer_id"] = seeder.upsert_default_event_organizer(admin_unit_id)
|
||||
|
||||
elif free_text_suffix:
|
||||
data["event_place_id_suffix"] = "Place address"
|
||||
data["organizer_id_suffix"] = "Organizer address"
|
||||
|
||||
if db_error:
|
||||
utils.mock_db_commit(mocker)
|
||||
|
||||
@ -121,7 +134,7 @@ def test_event_suggestion_create_for_admin_unit(
|
||||
)
|
||||
|
||||
if missing_preview_field:
|
||||
assert preview_response.status_code == 406
|
||||
utils.assert_response_error_message(preview_response)
|
||||
return
|
||||
|
||||
utils.assert_response_ok(preview_response)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user