mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
Veranstaltungen mit mehreren Terminen und unterschiedlichen Uhrzeiten #333
This commit is contained in:
parent
eed987524a
commit
1167f2ce8d
@ -8,6 +8,9 @@ describe("Event", () => {
|
||||
cy.get("#name").type("Stadtfest");
|
||||
cy.checkEventStartEnd(false, test.recurrence, "date_definitions-0-");
|
||||
|
||||
cy.get("#add-date-defintion-btn").click();
|
||||
cy.checkEventStartEnd(false, test.recurrence, "date_definitions-1-");
|
||||
|
||||
cy.select2("event_place_id", "Neu");
|
||||
cy.get("#new_event_place-location-city").type("Goslar");
|
||||
cy.get("#new_place_container_search_link").click();
|
||||
@ -28,6 +31,9 @@ describe("Event", () => {
|
||||
cy.contains("a", "Veranstaltung bearbeiten").click();
|
||||
cy.url().should("include", "/update");
|
||||
cy.checkEventStartEnd(true, test.recurrence, "date_definitions-0-");
|
||||
|
||||
cy.get('div[data-prefix=date_definitions-1-] .remove-date-defintion-btn:visible').click()
|
||||
|
||||
cy.get("#submit").click();
|
||||
cy.url().should(
|
||||
"include",
|
||||
|
||||
@ -223,7 +223,7 @@ Cypress.Commands.add(
|
||||
if (update && recurrence) {
|
||||
cy.get('#' + prefix + 'single-event-container').should("not.be.visible");
|
||||
cy.get('#' + prefix + 'recc-event-container').should("be.visible");
|
||||
cy.get('[name="riedit"]').click();
|
||||
cy.get('div[data-prefix=' + prefix + '] [name="riedit"]').click();
|
||||
} else {
|
||||
cy.checkEventAllday(prefix);
|
||||
|
||||
@ -233,8 +233,8 @@ Cypress.Commands.add(
|
||||
cy.get("#ui-datepicker-div").should("not.be.visible");
|
||||
|
||||
cy.get('#' + prefix + 'start-time').click();
|
||||
cy.get(".ui-timepicker-wrapper").should("be.visible");
|
||||
cy.get(".ui-timepicker-wrapper .ui-timepicker-am[data-time=0]").click(); // select 00:00
|
||||
cy.get(".ui-timepicker-wrapper:visible").should("be.visible");
|
||||
cy.get(".ui-timepicker-wrapper:visible .ui-timepicker-am[data-time=0]").click(); // select 00:00
|
||||
cy.get("#ui-datepicker-div").should("not.be.visible");
|
||||
|
||||
cy.get('#' + prefix + 'end-container').should("not.be.visible");
|
||||
@ -254,17 +254,17 @@ Cypress.Commands.add(
|
||||
}
|
||||
|
||||
cy.get(".modal-recurrence").should("be.visible");
|
||||
cy.inputsShouldHaveSameValue('#' + prefix + 'start-user', "#recc-start-user");
|
||||
cy.inputsShouldHaveSameValue('#' + prefix + 'start-time', "#recc-start-time");
|
||||
cy.get("#rirtemplate option").should("have.length", 4);
|
||||
cy.get(".modal-recurrence input[value=BYENDDATE]").should("be.checked");
|
||||
cy.get(".modal-recurrence .modal-footer .btn-primary").click();
|
||||
cy.inputsShouldHaveSameValue('#' + prefix + 'start-user', '#' + prefix + 'recc-start-user');
|
||||
cy.inputsShouldHaveSameValue('#' + prefix + 'start-time', '#' + prefix + 'recc-start-time');
|
||||
cy.get('#' + prefix + 'rirtemplate option').should("have.length", 4);
|
||||
cy.get(".modal-recurrence:visible input[value=BYENDDATE]").should("be.checked");
|
||||
cy.get(".modal-recurrence:visible .modal-footer .btn-primary").click();
|
||||
|
||||
cy.get('#' + prefix + 'single-event-container').should("not.be.visible");
|
||||
cy.get('#' + prefix + 'recc-event-container').should("be.visible");
|
||||
|
||||
if (recurrence == false) {
|
||||
cy.get('[name="ridelete"]').click();
|
||||
cy.get('[name="ridelete"]:visible').click();
|
||||
cy.get('#' + prefix + 'single-event-container').should("be.visible");
|
||||
cy.get('#' + prefix + 'recc-event-container').should("not.be.visible");
|
||||
cy.get('#' + prefix + 'end-container').should("not.be.visible");
|
||||
@ -284,14 +284,14 @@ Cypress.Commands.add(
|
||||
// Recurrence
|
||||
cy.get('#' + prefix + 'recc-button').click();
|
||||
cy.get(".modal-recurrence").should("be.visible");
|
||||
cy.get('#recc-allday').should("be.checked");
|
||||
cy.get('#recc-start-time').should("not.be.visible");
|
||||
cy.get('#recc-fo-end-time').should("not.be.visible");
|
||||
cy.get('#' + prefix + 'recc-allday').should("be.checked");
|
||||
cy.get('#' + prefix + 'recc-start-time').should("not.be.visible");
|
||||
cy.get('#' + prefix + 'recc-fo-end-time').should("not.be.visible");
|
||||
|
||||
cy.get('#recc-allday').click();
|
||||
cy.get('#recc-start-time').should("be.visible");
|
||||
cy.get('#recc-fo-end-time').should("be.visible");
|
||||
cy.get(".modal-recurrence .modal-footer .btn-secondary").click();
|
||||
cy.get('#' + prefix + 'recc-allday').click();
|
||||
cy.get('#' + prefix + 'recc-start-time').should("be.visible");
|
||||
cy.get('#' + prefix + 'recc-fo-end-time').should("be.visible");
|
||||
cy.get(".modal-recurrence:visible .modal-footer .btn-secondary").click();
|
||||
|
||||
// Turn off
|
||||
cy.get('#' + prefix + 'allday').click();
|
||||
|
||||
494
messages.pot
494
messages.pot
File diff suppressed because it is too large
Load Diff
@ -37,13 +37,13 @@ class EventDateDefinitionFormMixin:
|
||||
start = CustomDateTimeField(
|
||||
lazy_gettext("Start"),
|
||||
validators=[DataRequired()],
|
||||
description=lazy_gettext("Indicate when the event will take place."),
|
||||
description=lazy_gettext("Indicate when the event date will start."),
|
||||
)
|
||||
end = CustomDateTimeField(
|
||||
lazy_gettext("End"),
|
||||
validators=[Optional()],
|
||||
description=lazy_gettext(
|
||||
"Indicate when the event will end. An event can last a maximum of 14 days."
|
||||
"Indicate when the event date will end. An event can last a maximum of 14 days."
|
||||
),
|
||||
)
|
||||
allday = BooleanField(
|
||||
@ -235,6 +235,9 @@ class BaseEventForm(SharedEventForm):
|
||||
FormField(EventDateDefinitionForm, default=lambda: EventDateDefinition()),
|
||||
min_entries=1,
|
||||
)
|
||||
date_definition_template = FormField(
|
||||
EventDateDefinitionForm, default=lambda: EventDateDefinition()
|
||||
)
|
||||
previous_start_date = CustomDateTimeField(
|
||||
lazy_gettext("Previous start date"),
|
||||
validators=[Optional()],
|
||||
@ -330,6 +333,8 @@ class CreateEventForm(BaseEventForm):
|
||||
field.populate_obj(obj, "organizer")
|
||||
elif name == "photo" and not obj.photo:
|
||||
obj.photo = Image()
|
||||
elif name == "date_definition_template":
|
||||
continue
|
||||
field.populate_obj(obj, name)
|
||||
|
||||
obj.public_status = (
|
||||
@ -405,6 +410,8 @@ class UpdateEventForm(BaseEventForm):
|
||||
for name, field in self._fields.items():
|
||||
if name == "photo" and not obj.photo:
|
||||
obj.photo = Image()
|
||||
elif name == "date_definition_template":
|
||||
continue
|
||||
field.populate_obj(obj, name)
|
||||
|
||||
if obj.photo and obj.photo.is_empty():
|
||||
|
||||
@ -909,9 +909,10 @@ class Event(db.Model, TrackableMixin, EventMixin):
|
||||
@min_start.expression
|
||||
def min_start(cls):
|
||||
return (
|
||||
select([EventDateDefinition.end])
|
||||
select([EventDateDefinition.start])
|
||||
.where(EventDateDefinition.event_id == cls.id)
|
||||
.order_by(EventDateDefinition.start)
|
||||
.limit(1)
|
||||
.as_scalar()
|
||||
)
|
||||
|
||||
@ -938,6 +939,7 @@ class Event(db.Model, TrackableMixin, EventMixin):
|
||||
|
||||
date_definitions = relationship(
|
||||
"EventDateDefinition",
|
||||
order_by="EventDateDefinition.start",
|
||||
backref=backref("event", lazy=False),
|
||||
cascade="all, delete-orphan",
|
||||
)
|
||||
|
||||
@ -349,6 +349,7 @@ def update_event_dates_with_recurrence_rule(event):
|
||||
None,
|
||||
)
|
||||
if existing_date:
|
||||
if existing_date in dates_to_remove:
|
||||
dates_to_remove.remove(existing_date)
|
||||
else:
|
||||
new_date = EventDate(
|
||||
|
||||
@ -108,3 +108,7 @@ div.errorarea {
|
||||
font-weight: bold;
|
||||
padding: 2px 10px;
|
||||
}
|
||||
|
||||
.recc-event-container .form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@ -207,6 +207,7 @@
|
||||
reccStartTime: 'Begin',
|
||||
reccFoEndTime: 'End',
|
||||
reccAllDay: 'All day',
|
||||
removeEventDate: 'Remove event date',
|
||||
});
|
||||
|
||||
|
||||
@ -257,15 +258,16 @@
|
||||
$.templates('occurrenceTmpl', OCCURRENCETMPL);
|
||||
|
||||
var DISPLAYTMPL = ['<div class="ridisplay">',
|
||||
'<div class="rimain bg-light mt-3 p-3 rounded border">',
|
||||
'<div class="rimain">',
|
||||
'<div class="mb-2">',
|
||||
'<div class="ridisplay-start"></div>',
|
||||
'<div class="ridisplay-times"></div>',
|
||||
'<div class="ridisplay">{{:i18n.displayUnactivate}}</div>',
|
||||
'</div>',
|
||||
'{{if !readOnly}}',
|
||||
'<button type="button" name="riedit" class="btn btn-outline-secondary">{{:i18n.add_rules}}</button>',
|
||||
'<button type="button" name="ridelete" class="btn btn-outline-secondary" style="display:none">{{:i18n.delete_rules}}</button>',
|
||||
'<button type="button" name="riedit" class="btn btn-outline-secondary"><i class="fa fa-plus"></i> {{:i18n.add_rules}}</button>',
|
||||
'<button type="button" name="ridelete" class="btn btn-outline-secondary" style="display:none"><i class="fa fa-times-circle"></i> {{:i18n.delete_rules}}</button>',
|
||||
'<button type="button" class="btn btn-outline-secondary remove-date-defintion-btn d-none"><i class="fa fa-calendar-minus"></i> {{:i18n.removeEventDate}}</button>',
|
||||
'{{/if}}',
|
||||
'</div>',
|
||||
'<div class="rioccurrences" style="display:none" /></div>'].join('\n');
|
||||
@ -284,37 +286,37 @@
|
||||
'<div class="modal-body">',
|
||||
'<div class="riform">',
|
||||
'<form>',
|
||||
'<div id="messagearea" style="display: none;">',
|
||||
'<div id="{{:prefix}}messagearea" style="display: none;">',
|
||||
'</div>',
|
||||
|
||||
'<div class="form-row">',
|
||||
'<div class="form-group col-md-4">',
|
||||
'<label class="mb-0" for="recc-start">{{:i18n.reccStart}}</label>',
|
||||
'<input type="text" class="form-control datepicker" data-range-to="#recc-end" data-allday="#recc-allday" id="recc-start" name="recc-start" required="" />',
|
||||
'<label class="mb-0" for="{{:prefix}}recc-start">{{:i18n.reccStart}}</label>',
|
||||
'<input type="text" class="form-control datepicker" data-range-to="#{{:prefix}}recc-end" data-allday="#{{:prefix}}recc-allday" id="{{:prefix}}recc-start" name="recc-start" required="" />',
|
||||
'</div>',
|
||||
|
||||
'<div class="form-group col-md-4" id="recc-start-time-group">',
|
||||
'<label class="mb-0" for="recc-start-time">{{:i18n.reccStartTime}}</label>',
|
||||
'<input type="text" class="form-control timepicker" id="recc-start-time" name="recc-start-time" required="" />',
|
||||
'<div class="form-group col-md-4" id="{{:prefix}}recc-start-time-group">',
|
||||
'<label class="mb-0" for="{{:prefix}}recc-start-time">{{:i18n.reccStartTime}}</label>',
|
||||
'<input type="text" class="form-control timepicker" id="{{:prefix}}recc-start-time" name="recc-start-time" required="" />',
|
||||
'</div>',
|
||||
|
||||
'<div class="form-group col-md-4" id="recc-fo-end-time-group">',
|
||||
'<label class="mb-0" for="recc-fo-end-time">{{:i18n.reccFoEndTime}}</label>',
|
||||
'<input type="text" class="form-control timepicker" id="recc-fo-end-time" name="recc-fo-end-time" />',
|
||||
'<div class="form-group col-md-4" id="{{:prefix}}recc-fo-end-time-group">',
|
||||
'<label class="mb-0" for="{{:prefix}}recc-fo-end-time">{{:i18n.reccFoEndTime}}</label>',
|
||||
'<input type="text" class="form-control timepicker" id="{{:prefix}}recc-fo-end-time" name="recc-fo-end-time" />',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div class="form-row">',
|
||||
'<div class="form-group col-md">',
|
||||
'<div class="form-check">',
|
||||
'<input class="form-check-input" id="recc-allday" name="recc-allday" type="checkbox" value="y">',
|
||||
'<label class="form-check-label" for="recc-allday">{{:i18n.reccAllDay}}</label>',
|
||||
'<input class="form-check-input" id="{{:prefix}}recc-allday" name="recc-allday" type="checkbox" value="y">',
|
||||
'<label class="form-check-label" for="{{:prefix}}recc-allday">{{:i18n.reccAllDay}}</label>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div class="form-row">',
|
||||
'<div id="rirangeoptions" class="form-group col-md">',
|
||||
'<div id="{{:prefix}}rirangeoptions" class="form-group col-md">',
|
||||
'<label class="mb-0">{{:i18n.range}}</label>',
|
||||
'<div class="input-group mb-1">',
|
||||
'<div class="input-group-prepend">',
|
||||
@ -325,14 +327,14 @@
|
||||
'value="BYENDDATE"',
|
||||
'name="rirangetype"',
|
||||
'class="form-check-inline"',
|
||||
'id="{{:name}}rangetype:BYENDDATE"/>',
|
||||
'id="{{:prefix}}{{:name}}rangetype:BYENDDATE"/>',
|
||||
'{{:i18n.rangeByEndDate}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<input',
|
||||
'type="text"',
|
||||
'class="form-control"',
|
||||
'name="rirangebyenddatecalendar" id="recc-end" />',
|
||||
'name="rirangebyenddatecalendar" id="{{:prefix}}recc-end" />',
|
||||
'</div>',
|
||||
'<div class="input-group mb-1">',
|
||||
'<div class="input-group-prepend">',
|
||||
@ -342,7 +344,7 @@
|
||||
'value="BYOCCURRENCES"',
|
||||
'name="rirangetype"',
|
||||
'class="form-check-inline"',
|
||||
'id="{{:name}}rangetype:BYOCCURRENCES"/>',
|
||||
'id="{{:prefix}}{{:name}}rangetype:BYOCCURRENCES"/>',
|
||||
'{{:i18n.rangeByOccurrences1}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
@ -365,7 +367,7 @@
|
||||
'value="NOENDDATE"',
|
||||
'name="rirangetype"',
|
||||
'class="form-check-inline"',
|
||||
'id="{{:name}}rangetype:NOENDDATE"/>',
|
||||
'id="{{:prefix}}{{:name}}rangetype:NOENDDATE"/>',
|
||||
'{{:i18n.rangeNoEnd}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
@ -378,7 +380,7 @@
|
||||
'<label for="{{:name}}rtemplate" class="mb-0">',
|
||||
'{{:i18n.recurrenceType}}',
|
||||
'</label>',
|
||||
'<select id="rirtemplate" name="rirtemplate" class="form-control">',
|
||||
'<select id="{{:prefix}}rirtemplate" name="rirtemplate" class="form-control">',
|
||||
'{{props rtemplate}}',
|
||||
'<option value="{{>key}}">{{:~root.i18n.rtemplate[key]}}</value>',
|
||||
'{{/props}}',
|
||||
@ -386,7 +388,7 @@
|
||||
'</div>',
|
||||
|
||||
'<div class="col-md">',
|
||||
'<div id="ridailyinterval" class="form-group rifield">',
|
||||
'<div id="{{:prefix}}ridailyinterval" class="form-group rifield">',
|
||||
'<label for="{{:name}}dailyinterval" class="mb-0">',
|
||||
'{{:i18n.dailyInterval1}}',
|
||||
'</label>',
|
||||
@ -395,7 +397,7 @@
|
||||
'value="1"',
|
||||
'name="ridailyinterval"',
|
||||
'class="form-control"',
|
||||
'id="{{:name}}dailyinterval" />',
|
||||
'id="{{:prefix}}{{:name}}dailyinterval" />',
|
||||
'<div class="input-group-append">',
|
||||
'<span class="input-group-text">',
|
||||
'{{:i18n.dailyInterval2}}',
|
||||
@ -403,7 +405,7 @@
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div id="riweeklyinterval" class="form-group rifield">',
|
||||
'<div id="{{:prefix}}riweeklyinterval" class="form-group rifield">',
|
||||
'<label for="{{:name}}weeklyinterval" class="mb-0">',
|
||||
'{{:i18n.weeklyInterval1}}',
|
||||
'</label>',
|
||||
@ -412,7 +414,7 @@
|
||||
'value="1"',
|
||||
'name="riweeklyinterval"',
|
||||
'class="form-control"',
|
||||
'id="{{:name}}riweeklyinterval" />',
|
||||
'id="{{:prefix}}{{:name}}riweeklyinterval" />',
|
||||
'<div class="input-group-append">',
|
||||
'<span class="input-group-text">',
|
||||
'{{:i18n.weeklyInterval2}}',
|
||||
@ -420,7 +422,7 @@
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div id="rimonthlyinterval" class="form-group rifield">',
|
||||
'<div id="{{:prefix}}rimonthlyinterval" class="form-group rifield">',
|
||||
'<label for="rimonthlyinterval" class="mb-0">{{:i18n.monthlyInterval1}}</label>',
|
||||
'<div class="input-group">',
|
||||
'<input type="text" size="2"',
|
||||
@ -434,7 +436,7 @@
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div id="riyearlyinterval" class="form-group rifield">',
|
||||
'<div id="{{:prefix}}riyearlyinterval" class="form-group rifield">',
|
||||
'<label for="riyearlyinterval" class="mb-0">{{:i18n.yearlyInterval1}}</label>',
|
||||
'<div class="input-group">',
|
||||
'<input type="text" size="2"',
|
||||
@ -451,14 +453,14 @@
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div id="riweeklyweekdays" class="form-group rifield">',
|
||||
'<div id="{{:prefix}}riweeklyweekdays" class="form-group rifield">',
|
||||
'<label for="{{:name}}weeklyinterval" class="mb-0">{{:i18n.weeklyWeekdays}}</label>',
|
||||
'<div>',
|
||||
'{{for orderedWeekdays itemVar=\'~value\'}}',
|
||||
'<div class="form-check form-check-inline">',
|
||||
'<input type="checkbox"',
|
||||
'name="riweeklyweekdays{{:~root.weekdays[~value]}}"',
|
||||
'id="{{:name}}weeklyWeekdays{{:~root.weekdays[~value]}}"',
|
||||
'id="{{:prefix}}{{:name}}weeklyWeekdays{{:~root.weekdays[~value]}}"',
|
||||
'class="form-check-input"',
|
||||
'value="{{:~root.weekdays[~value]}}" />',
|
||||
'<label for="{{:name}}weeklyWeekdays{{:~root.weekdays[~value]}}" class="form-check-label">{{:~root.i18n.shortWeekdays[~value]}}</label>',
|
||||
@ -466,7 +468,7 @@
|
||||
'{{/for}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div id="rimonthlyoptions" class="form-group rifield">',
|
||||
'<div id="{{:prefix}}rimonthlyoptions" class="form-group rifield">',
|
||||
'<label for="rimonthlytype" class="mb-0">{{:i18n.monthlyRepeatOn}}</label>',
|
||||
'<div>',
|
||||
'<div class="input-group mb-1">',
|
||||
@ -477,12 +479,12 @@
|
||||
'value="DAYOFMONTH"',
|
||||
'name="rimonthlytype"',
|
||||
'class="form-check-inline"',
|
||||
'id="{{:name}}monthlytype:DAYOFMONTH" />',
|
||||
'id="{{:prefix}}{{:name}}monthlytype:DAYOFMONTH" />',
|
||||
'{{:i18n.monthlyDayOfMonth1}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<select name="rimonthlydayofmonthday" class="form-control"',
|
||||
'id="{{:name}}monthlydayofmonthday">',
|
||||
'id="{{:prefix}}{{:name}}monthlydayofmonthday">',
|
||||
'{{for start=1 end=32}}',
|
||||
'<option value="{{:}}">{{:}}</option>',
|
||||
'{{/for}}',
|
||||
@ -501,7 +503,7 @@
|
||||
'value="WEEKDAYOFMONTH"',
|
||||
'name="rimonthlytype"',
|
||||
'class="form-check-inline"',
|
||||
'id="{{:name}}monthlytype:WEEKDAYOFMONTH" />',
|
||||
'id="{{:prefix}}{{:name}}monthlytype:WEEKDAYOFMONTH" />',
|
||||
'{{:i18n.monthlyWeekdayOfMonth1}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
@ -523,7 +525,7 @@
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div id="riyearlyoptions" class="form-group rifield">',
|
||||
'<div id="{{:prefix}}riyearlyoptions" class="form-group rifield">',
|
||||
'<label for="riyearlyType" class="mb-0">{{:i18n.yearlyRepeatOn}}</label>',
|
||||
'<div>',
|
||||
'<div class="input-group mb-1">',
|
||||
@ -534,7 +536,7 @@
|
||||
'value="DAYOFMONTH"',
|
||||
'name="riyearlyType"',
|
||||
'class="form-check-inline"',
|
||||
'id="{{:name}}yearlytype:DAYOFMONTH" />',
|
||||
'id="{{:prefix}}{{:name}}yearlytype:DAYOFMONTH" />',
|
||||
'{{:i18n.yearlyDayOfMonth1}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
@ -557,7 +559,7 @@
|
||||
'value="WEEKDAYOFMONTH"',
|
||||
'name="riyearlyType"',
|
||||
'class="form-check-inline"',
|
||||
'id="{{:name}}yearlytype:WEEKDAYOFMONTH"/>',
|
||||
'id="{{:prefix}}{{:name}}yearlytype:WEEKDAYOFMONTH"/>',
|
||||
'{{:i18n.yearlyWeekdayOfMonth1}}',
|
||||
'</div>',
|
||||
'</div>',
|
||||
@ -585,10 +587,10 @@
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div id="occurences-show-container">',
|
||||
'<a href="#" class="show-link" data-container="occurences-container" data-show-container="occurences-show-container"><i class="fa fa-chevron-down"></i> {{:i18n.preview}}</a>',
|
||||
'<div id="{{:prefix}}occurences-show-container">',
|
||||
'<a href="#" class="show-link" data-container="{{:prefix}}occurences-container" data-show-container="{{:prefix}}occurences-show-container"><i class="fa fa-chevron-down"></i> {{:i18n.preview}}</a>',
|
||||
'</div>',
|
||||
'<div id="occurences-container" style="display: none;">',
|
||||
'<div id="{{:prefix}}occurences-container" style="display: none;">',
|
||||
'<div class="rioccurrencesactions">',
|
||||
'<div class="rioccurancesheader">',
|
||||
'<h2 class="my-2">{{:i18n.preview}}',
|
||||
@ -609,15 +611,15 @@
|
||||
'<div class="input-group-prepend">',
|
||||
'<span class="input-group-text">{{:i18n.addDate}}</span>',
|
||||
'</div>',
|
||||
'<input type="text" class="form-control" name="adddate" id="adddate" />',
|
||||
'<input type="text" class="form-control" name="adddate" id="{{:prefix}}adddate" />',
|
||||
'<div class="input-group-append">',
|
||||
'<input type="button" class="btn btn-outline-secondary" name="addoccurencebtn" id="addoccurencebtn" value="{{:i18n.add}}" />',
|
||||
'<input type="button" class="btn btn-outline-secondary" name="addoccurencebtn" id="{{:prefix}}addoccurencebtn" value="{{:i18n.add}}" />',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="mt-3" id="occurences-hide-container">',
|
||||
'<a href="#" class="hide-link" data-container="occurences-container" data-show-container="occurences-show-container"><i class="fa fa-chevron-up"></i> {{:i18n.preview}}</a>',
|
||||
'<div class="mt-3" id="{{:prefix}}occurences-hide-container">',
|
||||
'<a href="#" class="hide-link" data-container="{{:prefix}}occurences-container" data-show-container="{{:prefix}}occurences-show-container"><i class="fa fa-chevron-up"></i> {{:i18n.preview}}</a>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'</form>',
|
||||
@ -649,9 +651,9 @@
|
||||
var day, month, year, interval, yearlyType, occurrences, date;
|
||||
|
||||
for (i = 0; i < rtemplate.fields.length; i++) {
|
||||
field = form.find('#' + rtemplate.fields[i]);
|
||||
field = form.find('#' + conf.prefix + rtemplate.fields[i]);
|
||||
|
||||
switch (field.attr('id')) {
|
||||
switch (rtemplate.fields[i]) {
|
||||
|
||||
case 'ridailyinterval':
|
||||
interval = field.find('input[name=ridailyinterval]').val();
|
||||
@ -1017,8 +1019,8 @@
|
||||
}
|
||||
|
||||
for (i = 0; i < rtemplate.fields.length; i++) {
|
||||
field = form.find('#' + rtemplate.fields[i]);
|
||||
switch (field.attr('id')) {
|
||||
field = form.find('#' + conf.prefix + rtemplate.fields[i]);
|
||||
switch (rtemplate.fields[i]) {
|
||||
|
||||
case 'ridailyinterval':
|
||||
field.find('input[name=ridailyinterval]').val(interval);
|
||||
@ -1150,7 +1152,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
var messagearea = form.find('#messagearea');
|
||||
var messagearea = form.find('#' + conf.prefix + 'messagearea');
|
||||
if (unsupportedFeatures.length !== 0) {
|
||||
messagearea.text(conf.i18n.unsupportedFeatures + ' ' + unsupportedFeatures.join('; '));
|
||||
messagearea.show();
|
||||
@ -1200,7 +1202,7 @@
|
||||
if (value) {
|
||||
var rtemplate = conf.rtemplate[value];
|
||||
for (i = 0; i < rtemplate.fields.length; i++) {
|
||||
form.find('#' + rtemplate.fields[i]).show();
|
||||
form.find('#' + conf.prefix + rtemplate.fields[i]).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1241,7 +1243,7 @@
|
||||
function occurrenceAdd(event) {
|
||||
event.preventDefault();
|
||||
var dateinput = form
|
||||
.find('.riaddoccurrence input#adddate');
|
||||
.find('.riaddoccurrence input#' + conf.prefix + 'adddate');
|
||||
var datevalue = $.datepicker.formatDate("yymmdd", dateinput.data('picker').datepicker("getDate")) + 'T000000';
|
||||
if (form.ical.RDATE === undefined) {
|
||||
form.ical.RDATE = [];
|
||||
@ -1382,7 +1384,7 @@
|
||||
var startdate = null;
|
||||
var startField, startFieldYear, startFieldMonth, startFieldDay;
|
||||
|
||||
var startField = 'recc-start'; // conf.startField;
|
||||
var startField = conf.prefix + 'recc-start'; // conf.startField;
|
||||
|
||||
// Find the default byday and bymonthday from the start date, if any:
|
||||
if (startField) {
|
||||
@ -1541,7 +1543,7 @@
|
||||
// if (startdate !== null) {
|
||||
// loadOccurrences(startdate, widgetSaveToRfc5545(form, conf, false).result, 0, true);
|
||||
// }
|
||||
display.find('button[name="riedit"]').text(conf.i18n.edit_rules);
|
||||
display.find('button[name="riedit"]').html('<i class="fa fa-edit"></i> ' + conf.i18n.edit_rules);
|
||||
display.find('button[name="ridelete"]').show();
|
||||
|
||||
displayOn();
|
||||
@ -1557,7 +1559,7 @@
|
||||
label.text(conf.i18n.displayUnactivate);
|
||||
textarea.val('').change(); // Clear the textarea.
|
||||
display.find('.rioccurrences').hide();
|
||||
display.find('button[name="riedit"]').text(conf.i18n.add_rules);
|
||||
display.find('button[name="riedit"]').html('<i class="fa fa-plus"></i>' + conf.i18n.add_rules);
|
||||
display.find('button[name="ridelete"]').hide();
|
||||
|
||||
set_picker_date($('#' + conf.prefix + 'end-user'), null);
|
||||
@ -1571,7 +1573,7 @@
|
||||
startDate = findStartDate();
|
||||
|
||||
// Hide any error message from before
|
||||
messagearea = form.find('#messagearea');
|
||||
messagearea = form.find('#' + conf.prefix + 'messagearea');
|
||||
messagearea.text('');
|
||||
messagearea.hide();
|
||||
|
||||
@ -1579,7 +1581,7 @@
|
||||
form.find('.riaddoccurrence div.errorarea').text('').hide();
|
||||
|
||||
// Repeats Daily
|
||||
if (form.find('#ridailyinterval').css('display') === 'block') {
|
||||
if (form.find('#' + conf.prefix + 'ridailyinterval').css('display') === 'block') {
|
||||
// Check repeat every field
|
||||
num = findIntField('ridailyinterval', form);
|
||||
if (!num || num < 1 || num > 1000) {
|
||||
@ -1589,7 +1591,7 @@
|
||||
}
|
||||
|
||||
// Repeats Weekly
|
||||
if (form.find('#riweeklyinterval').css('display') === 'block') {
|
||||
if (form.find('#' + conf.prefix + 'riweeklyinterval').css('display') === 'block') {
|
||||
// Check repeat every field
|
||||
num = findIntField('riweeklyinterval', form);
|
||||
if (!num || num < 1 || num > 1000) {
|
||||
@ -1599,7 +1601,7 @@
|
||||
}
|
||||
|
||||
// Repeats Monthly
|
||||
if (form.find('#rimonthlyinterval').css('display') === 'block') {
|
||||
if (form.find('#' + conf.prefix + 'rimonthlyinterval').css('display') === 'block') {
|
||||
// Check repeat every field
|
||||
num = findIntField('rimonthlyinterval', form);
|
||||
if (!num || num < 1 || num > 1000) {
|
||||
@ -1615,7 +1617,7 @@
|
||||
}
|
||||
|
||||
// Repeats Yearly
|
||||
if (form.find('#riyearlyinterval').css('display') === 'block') {
|
||||
if (form.find('#' + conf.prefix + 'riyearlyinterval').css('display') === 'block') {
|
||||
// Check repeat every field
|
||||
num = findIntField('riyearlyinterval', form);
|
||||
if (!num || num < 1 || num > 1000) {
|
||||
@ -1781,7 +1783,11 @@
|
||||
recc_fo_end_time.timepicker('option', 'minTime', $(this).timepicker("getTime"));
|
||||
});
|
||||
|
||||
form.find('input[id=recc-start-user]').datepicker("setDate", $('#' + conf.prefix + 'start-user').datepicker("getDate"));
|
||||
var recc_start_picker = form.find('input[id=' + conf.prefix + 'recc-start-user]');
|
||||
var start_date = $('#' + conf.prefix + 'start-user').datepicker("getDate");
|
||||
recc_start_picker.datepicker("setDate", start_date);
|
||||
set_date_bounds(recc_start_picker);
|
||||
|
||||
recc_start_time.timepicker('setTime', $('#' + conf.prefix + 'start-time').timepicker("getTime"));
|
||||
recc_start_time.change();
|
||||
recc_fo_end_time.timepicker('setTime', $('#' + conf.prefix + 'end-time').timepicker("getTime"));
|
||||
@ -1789,8 +1795,8 @@
|
||||
var recc_allday = form.find('input[name=recc-allday]');
|
||||
recc_allday.prop('checked', $('#' + conf.prefix + 'allday').is(':checked'));
|
||||
var allday_checked = recc_allday.is(':checked');
|
||||
var recc_start_time_group = form.find("#recc-start-time-group");
|
||||
var recc_fo_end_time_group = form.find('#recc-fo-end-time-group');
|
||||
var recc_start_time_group = form.find("#" + conf.prefix + "recc-start-time-group");
|
||||
var recc_fo_end_time_group = form.find("#" + conf.prefix + "recc-fo-end-time-group");
|
||||
recc_start_time_group.toggle(!allday_checked);
|
||||
recc_fo_end_time_group.toggle(!allday_checked);
|
||||
|
||||
@ -1798,7 +1804,7 @@
|
||||
recc_start_time_group.toggle(!this.checked);
|
||||
recc_fo_end_time_group.toggle(!this.checked);
|
||||
|
||||
onAlldayChecked(this, "recc-start");
|
||||
onAlldayChecked(this, conf.prefix + "recc-start");
|
||||
|
||||
var end_moment = get_moment_with_time_from_fields(form.find('input[name=recc-start]'), form.find('input[name=recc-start-time]'));
|
||||
if (this.checked) {
|
||||
@ -1809,11 +1815,11 @@
|
||||
recc_fo_end_time.timepicker('setTime', end_moment.toDate());
|
||||
});
|
||||
|
||||
form.find('#occurences-show-container .show-link').click(function(e){
|
||||
form.find('#' + conf.prefix + 'occurences-show-container .show-link').click(function(e){
|
||||
showLink(e, this);
|
||||
});
|
||||
|
||||
form.find('#occurences-hide-container .hide-link').click(function(e){
|
||||
form.find('#' + conf.prefix + 'occurences-hide-container .hide-link').click(function(e){
|
||||
hideLink(e, this);
|
||||
});
|
||||
|
||||
@ -1822,9 +1828,9 @@
|
||||
});
|
||||
|
||||
// Pop up the little add form when clicking "Add"
|
||||
var riaddoccurrence_input = form.find('div.riaddoccurrence input#adddate');
|
||||
var riaddoccurrence_input = form.find('div.riaddoccurrence input#' + conf.prefix + 'adddate');
|
||||
start_datepicker(riaddoccurrence_input).datepicker("setDate", moment().toDate());
|
||||
form.find('input#addoccurencebtn').click(occurrenceAdd);
|
||||
form.find('input#' + conf.prefix + 'addoccurencebtn').click(occurrenceAdd);
|
||||
|
||||
// When the reload button is clicked, reload
|
||||
form.find('a.rirefreshbutton').click(
|
||||
@ -1876,7 +1882,7 @@
|
||||
form.find('.risavebutton').click(save);
|
||||
|
||||
$('#' + conf.prefix + 'recc-button').click(function() {
|
||||
$('button[name=riedit]').click();
|
||||
display.find('button[name="riedit"]').click();
|
||||
});
|
||||
|
||||
/*
|
||||
@ -1926,12 +1932,12 @@
|
||||
jQuery.tools.recurrenceinput.localize("de", {
|
||||
displayUnactivate: "Keine Wiederholungen",
|
||||
displayActivate: "Alle ",
|
||||
edit_rules: "Bearbeiten...",
|
||||
edit_rules: "Serie bearbeiten...",
|
||||
add_rules: "Hinzufügen...",
|
||||
delete_rules: "Löschen",
|
||||
delete_rules: "Serie zurücksetzen",
|
||||
add: "Hinzufügen",
|
||||
refresh: "Aktualisieren",
|
||||
title: "Regelmäßige Veranstaltung",
|
||||
title: "Serientermin",
|
||||
preview: "Ausgewählte Termine",
|
||||
addDate: "Termin hinzufügen",
|
||||
recurrenceType: "Wiederholt sich",
|
||||
@ -2050,4 +2056,5 @@ jQuery.tools.recurrenceinput.localize("de", {
|
||||
reccStartTime: "Beginn",
|
||||
reccFoEndTime: "Ende",
|
||||
reccAllDay: "Ganztägig",
|
||||
removeEventDate: 'Termin entfernen',
|
||||
});
|
||||
@ -369,14 +369,15 @@ function scroll_to_element(element, complete) {
|
||||
var alldayInput = container.find("input[id$='-allday']");
|
||||
var recurrenceRuleTextarea = container.find("textarea[id$='-recurrence_rule']");
|
||||
|
||||
start_datepicker(startInput);
|
||||
start_datepicker(endInput);
|
||||
|
||||
start_timepicker(startTimeInput);
|
||||
start_timepicker(endTimeInput);
|
||||
|
||||
start_datepicker(startInput);
|
||||
start_datepicker(endInput);
|
||||
|
||||
recurrenceRuleTextarea.recurrenceinput({prefix: prefix, ajaxURL: "/events/rrule"});
|
||||
|
||||
var removeButton = container.find("button.remove-date-defintion-btn");
|
||||
var startUserInput = container.find("input[id$='-start-user']");
|
||||
var endUserInput = container.find("input[id$='-end-user']");
|
||||
|
||||
@ -409,6 +410,28 @@ function scroll_to_element(element, complete) {
|
||||
}
|
||||
});
|
||||
|
||||
removeButton.click(function () {
|
||||
var count = $.find(".date-definition-container").length;
|
||||
if (count > 1) {
|
||||
var container = $(this).closest(".date-definition-container");
|
||||
container.remove();
|
||||
count--;
|
||||
|
||||
if (count == 1) {
|
||||
$('.date-definition-container button.remove-date-defintion-btn').addClass("d-none");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
container.find(".show-link").click(function (e) {
|
||||
showLink(e, this);
|
||||
});
|
||||
|
||||
container.find(".hide-link").click(function (e) {
|
||||
hideLink(e, this);
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.ovedaDateDefinition = function(options) {
|
||||
@ -433,11 +456,11 @@ function scroll_to_element(element, complete) {
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$(".datepicker").each(function (index, element) {
|
||||
$("form .datepicker").each(function (index, element) {
|
||||
start_datepicker($(element));
|
||||
});
|
||||
|
||||
$(".timepicker").each(function (index, element) {
|
||||
$("form .timepicker").each(function (index, element) {
|
||||
start_timepicker($(element));
|
||||
});
|
||||
|
||||
|
||||
@ -667,7 +667,7 @@
|
||||
<h2 class="mt-0"><a name="event-dates">{{ _('Event Dates') }}</a></div>
|
||||
<div class="list-group list-group-flush mb-4" style="max-height: 30vh; overflow: scroll; overflow-y: auto;">
|
||||
{% for date in dates %}
|
||||
<a href="{{ url_for('event_date', id=date.id) }}" class="list-group-item">{{ date.start | dateformat('full') }}</a>
|
||||
<a href="{{ url_for('event_date', id=date.id) }}" class="list-group-item">{{ render_event_date(date.start, date.end, date.allday) }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
@ -1645,4 +1645,64 @@ $('#allday').on('change', function() {
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='jquery.recurrenceinput.css')}}" />
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_event_date_defintion_code() %}
|
||||
$('.date-definition-container').ovedaDateDefinition();
|
||||
var min_date_definition_index = $(".date-definition-container").length;
|
||||
if (min_date_definition_index > 1) {
|
||||
$('.date-definition-container button.remove-date-defintion-btn').removeClass("d-none");
|
||||
}
|
||||
|
||||
$("#add-date-defintion-btn").click(function () {
|
||||
var template = $(".date-definition-template");
|
||||
var template_prefix = template.attr('data-prefix');
|
||||
|
||||
var last_container = $(".date-definition-container:last");
|
||||
var last_prefix = last_container.attr('data-prefix');
|
||||
var new_index = Math.max(min_date_definition_index, $(".date-definition-container").length);
|
||||
min_date_definition_index++;
|
||||
|
||||
var new_prefix = last_prefix.replace(/-(\d+)-$/g, function(match, number) {
|
||||
return '-' + new_index + '-';
|
||||
});
|
||||
|
||||
var new_container = template.clone();
|
||||
new_container.removeClass('date-definition-template');
|
||||
new_container.removeClass('d-none');
|
||||
new_container.addClass('date-definition-container');
|
||||
new_container.attr('data-prefix', new_prefix);
|
||||
new_container.find("*").each(function() {
|
||||
var subelement = $(this);
|
||||
$.each(this.attributes, function(i, attrib) {
|
||||
subelement.attr(attrib.name, attrib.value.replace(template_prefix, new_prefix));
|
||||
});
|
||||
});
|
||||
|
||||
last_container.after(new_container);
|
||||
new_container.ovedaDateDefinition();
|
||||
|
||||
if ($.find(".date-definition-container").length > 1) {
|
||||
$('.date-definition-container button.remove-date-defintion-btn').removeClass("d-none");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_date_definition_container(date_definition, container_class="date-definition-container") %}
|
||||
<div class="{{ container_class }} card mb-3 bg-light" data-prefix="{{ date_definition.id }}-">
|
||||
<div class="card-body">
|
||||
<div id="{{ date_definition.id }}-single-event-container">
|
||||
{{ date_definition.form.hidden_tag() }}
|
||||
{{ render_field_with_errors(date_definition.form.start, **{"data-range-to":"#"+date_definition.form.end.id, "data-range-max-days": "14", "data-allday": "#"+date_definition.form.allday.id}) }}
|
||||
{{ render_field_with_errors(date_definition.form.end, is_collapsible=1) }}
|
||||
{{ render_field_with_errors(date_definition.form.allday, ri="checkbox") }}
|
||||
|
||||
<button type="button" id="{{ date_definition.id }}-recc-button" class="btn btn-outline-secondary"><i class="fas fa-history"></i> {{ _('Recurring event') }}</button>
|
||||
<button type="button" class="btn btn-outline-secondary remove-date-defintion-btn d-none"><i class="fa fa-calendar-minus"></i> {{ _('Remove event date') }}</button>
|
||||
</div>
|
||||
<div id="{{ date_definition.id }}-recc-event-container" class="recc-event-container">
|
||||
{{ render_field_with_errors(date_definition.form.recurrence_rule, label_hidden=True) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{% extends "layout.html" %}
|
||||
{% from "_macros.html" import render_manage_form_styles, render_manage_form_scripts, render_cropper_header, render_end_container_handling, render_jquery_steps_header, render_cropper_header, render_cropper_code, render_crop_image_form_section, render_radio_buttons, render_field_with_errors, render_field %}
|
||||
{% from "_macros.html" import render_event_date_defintion_code, render_date_definition_container, render_manage_form_styles, render_manage_form_scripts, render_cropper_header, render_end_container_handling, render_jquery_steps_header, render_cropper_header, render_cropper_code, render_crop_image_form_section, render_radio_buttons, render_field_with_errors, render_field %}
|
||||
|
||||
{%- block title -%}
|
||||
{{ _('Create event') }}
|
||||
@ -56,7 +56,7 @@ $( function() {
|
||||
}
|
||||
});
|
||||
|
||||
$('.date-definition-container').ovedaDateDefinition();
|
||||
{{ render_event_date_defintion_code() }}
|
||||
|
||||
function update_place_container(value) {
|
||||
switch (value) {
|
||||
@ -240,6 +240,8 @@ $( function() {
|
||||
|
||||
<h1>{{ _('Create event') }}</h1>
|
||||
|
||||
{{ render_date_definition_container(form.date_definition_template, "date-definition-template d-none") }}
|
||||
|
||||
<form id="main-form" action="" method="POST" enctype="multipart/form-data">
|
||||
{{ form.hidden_tag() }}
|
||||
|
||||
@ -255,22 +257,14 @@ $( function() {
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
{{ _('Event date') }}
|
||||
{{ _('Event dates') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-body pb-3">
|
||||
{% for date_definition in form.date_definitions %}
|
||||
<div class="date-definition-container" data-prefix="{{ date_definition.id }}-">
|
||||
<div id="{{ date_definition.id }}-single-event-container">
|
||||
{{ render_field_with_errors(date_definition.form.start, **{"data-range-to":"#"+date_definition.form.end.id, "data-range-max-days": "14", "data-allday": "#"+date_definition.form.allday.id}) }}
|
||||
{{ render_field_with_errors(date_definition.form.allday, ri="checkbox") }}
|
||||
{{ render_field_with_errors(date_definition.form.end, is_collapsible=1) }}
|
||||
<button type="button" id="{{ date_definition.id }}-recc-button" class="btn btn-outline-secondary"><i class="fas fa-history"></i> {{ _('Recurring event') }}</button>
|
||||
</div>
|
||||
<div id="{{ date_definition.id }}-recc-event-container">
|
||||
{{ render_field_with_errors(date_definition.form.recurrence_rule) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ render_date_definition_container(date_definition) }}
|
||||
{% endfor %}
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary btn-small" id="add-date-defintion-btn"><i class="fa fa-calendar-plus"></i> {{ _('Add event date') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{% extends "layout.html" %}
|
||||
{% from "_macros.html" import render_manage_form_styles, render_manage_form_scripts, render_cropper_header, render_end_container_handling, render_jquery_steps_header, render_cropper_code, render_crop_image_form_section, render_radio_buttons, render_field_with_errors, render_field %}
|
||||
{% from "_macros.html" import render_event_date_defintion_code, render_date_definition_container, render_manage_form_styles, render_manage_form_scripts, render_cropper_header, render_end_container_handling, render_jquery_steps_header, render_cropper_code, render_crop_image_form_section, render_radio_buttons, render_field_with_errors, render_field %}
|
||||
|
||||
{%- block title -%}
|
||||
{{ _('Update event') }}
|
||||
@ -27,7 +27,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
$('.date-definition-container').ovedaDateDefinition();
|
||||
{{ render_event_date_defintion_code() }}
|
||||
|
||||
// Organizer
|
||||
var organizer_select =$('#organizer_id');
|
||||
@ -131,6 +131,8 @@
|
||||
|
||||
<h1>{{ _('Update event') }}</h1>
|
||||
|
||||
{{ render_date_definition_container(form.date_definition_template, "date-definition-template d-none") }}
|
||||
|
||||
<form id="main-form" action="{{ url_for('event_update', event_id=event.id) }}" method="POST" enctype="multipart/form-data">
|
||||
{{ form.hidden_tag() }}
|
||||
|
||||
@ -146,22 +148,14 @@
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
{{ _('Event date') }}
|
||||
{{ _('Event dates') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="card-body pb-3">
|
||||
{% for date_definition in form.date_definitions %}
|
||||
<div class="date-definition-container" data-prefix="{{ date_definition.id }}-">
|
||||
<div id="{{ date_definition.id }}-single-event-container">
|
||||
{{ render_field_with_errors(date_definition.form.start, **{"data-range-to":"#"+date_definition.form.end.id, "data-range-max-days": "14", "data-allday": "#"+date_definition.form.allday.id}) }}
|
||||
{{ render_field_with_errors(date_definition.form.allday, ri="checkbox") }}
|
||||
{{ render_field_with_errors(date_definition.form.end, is_collapsible=1) }}
|
||||
<button type="button" id="{{ date_definition.id }}-recc-button" class="btn btn-outline-secondary"><i class="fas fa-history"></i> {{ _('Recurring event') }}</button>
|
||||
</div>
|
||||
<div id="{{ date_definition.id }}-recc-event-container">
|
||||
{{ render_field_with_errors(date_definition.form.recurrence_rule) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ render_date_definition_container(date_definition) }}
|
||||
{% endfor %}
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary btn-small" id="add-date-defintion-btn"><i class="fa fa-calendar-plus"></i> {{ _('Add event date') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -149,6 +149,7 @@ def event_create_for_admin_unit_id(id):
|
||||
prepare_event_form_for_suggestion(form, event_suggestion)
|
||||
if form.is_submitted():
|
||||
form.process(request.form)
|
||||
prepare_date_definition(form)
|
||||
|
||||
if form.validate_on_submit():
|
||||
event = Event()
|
||||
@ -310,8 +311,15 @@ def prepare_event_form(form):
|
||||
prepare_organizer(form)
|
||||
prepare_event_place(form)
|
||||
|
||||
prepare_date_definition(form)
|
||||
|
||||
|
||||
def prepare_date_definition(form):
|
||||
next_full_hour = get_next_full_hour()
|
||||
form.date_definition_template.start.data = next_full_hour
|
||||
|
||||
if not form.date_definitions[0].start.data:
|
||||
form.date_definitions[0].start.data = get_next_full_hour()
|
||||
form.date_definitions[0].start.data = next_full_hour
|
||||
|
||||
|
||||
def prepare_event_form_for_suggestion(form, event_suggestion):
|
||||
|
||||
@ -157,8 +157,10 @@ def create_put(
|
||||
return data
|
||||
|
||||
|
||||
@pytest.mark.parametrize("legacy", [True, False])
|
||||
def test_put(client, seeder, utils, app, mocker, legacy):
|
||||
@pytest.mark.parametrize(
|
||||
"variant", ["normal", "legacy", "recurrence", "two_date_definitions"]
|
||||
)
|
||||
def test_put(client, seeder, utils, app, mocker, variant):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
place_id = seeder.upsert_default_event_place(admin_unit_id)
|
||||
@ -166,7 +168,7 @@ def test_put(client, seeder, utils, app, mocker, legacy):
|
||||
|
||||
utils.mock_now(mocker, 2020, 1, 1)
|
||||
|
||||
put = create_put(place_id, organizer_id)
|
||||
put = create_put(place_id, organizer_id, legacy=(variant == "legacy"))
|
||||
put["rating"] = 10
|
||||
put["description"] = "Neue Beschreibung"
|
||||
put["external_link"] = "http://www.google.de"
|
||||
@ -186,9 +188,12 @@ def test_put(client, seeder, utils, app, mocker, legacy):
|
||||
put["price_info"] = "Erwachsene 5€, Kinder 2€."
|
||||
put["public_status"] = "draft"
|
||||
|
||||
if not legacy:
|
||||
if variant == "recurrence":
|
||||
put["date_definitions"][0]["recurrence_rule"] = "RRULE:FREQ=DAILY;COUNT=7"
|
||||
|
||||
if variant == "two_date_definitions":
|
||||
put["date_definitions"].append({"start": "2021-02-07T12:00:00.000Z"})
|
||||
|
||||
url = utils.get_url("api_v1_event", id=event_id)
|
||||
response = utils.put_json(url, put)
|
||||
utils.assert_response_no_content(response)
|
||||
@ -225,16 +230,23 @@ def test_put(client, seeder, utils, app, mocker, legacy):
|
||||
assert event.price_info == put["price_info"]
|
||||
assert event.public_status == PublicStatus.draft
|
||||
|
||||
if variant == "two_date_definitions":
|
||||
assert len(event.date_definitions) == 2
|
||||
else:
|
||||
assert len(event.date_definitions) == 1
|
||||
|
||||
len_dates = len(event.dates)
|
||||
|
||||
if legacy:
|
||||
assert len_dates == 1
|
||||
else:
|
||||
if variant == "recurrence":
|
||||
assert (
|
||||
event.date_definitions[0].recurrence_rule
|
||||
== put["date_definitions"][0]["recurrence_rule"]
|
||||
)
|
||||
assert len_dates == 7
|
||||
elif variant == "two_date_definitions":
|
||||
assert len_dates == 2
|
||||
else:
|
||||
assert len_dates == 1
|
||||
|
||||
|
||||
def test_put_invalidRecurrenceRule(client, seeder, utils, app):
|
||||
|
||||
@ -177,16 +177,18 @@ def prepare_events_post_data(seeder, utils, legacy=False):
|
||||
return url, data, admin_unit_id, place_id, organizer_id
|
||||
|
||||
|
||||
@pytest.mark.parametrize("allday", [True, False])
|
||||
@pytest.mark.parametrize("legacy", [True, False])
|
||||
def test_events_post(client, seeder, utils, app, allday, legacy):
|
||||
@pytest.mark.parametrize("variant", ["allday", "legacy", "two_date_definitions"])
|
||||
def test_events_post(client, seeder, utils, app, variant):
|
||||
url, data, admin_unit_id, place_id, organizer_id = prepare_events_post_data(
|
||||
seeder, utils, legacy
|
||||
seeder, utils, variant == "legacy"
|
||||
)
|
||||
|
||||
if allday and not legacy:
|
||||
if variant == "allday":
|
||||
data["date_definitions"][0]["allday"] = "1"
|
||||
|
||||
if variant == "two_date_definitions":
|
||||
data["date_definitions"].append({"start": "2021-02-07T12:00:00.000Z"})
|
||||
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_created(response)
|
||||
assert "id" in response.json
|
||||
@ -205,7 +207,12 @@ def test_events_post(client, seeder, utils, app, allday, legacy):
|
||||
assert event.photo is not None
|
||||
assert event.photo.encoding_format == "image/png"
|
||||
assert event.public_status == PublicStatus.published
|
||||
assert event.date_definitions[0].allday == (allday and not legacy)
|
||||
assert event.date_definitions[0].allday == (variant == "allday")
|
||||
|
||||
if variant == "two_date_definitions":
|
||||
assert len(event.date_definitions) == 2
|
||||
else:
|
||||
assert len(event.date_definitions) == 1
|
||||
|
||||
|
||||
def test_events_post_co_organizers(client, seeder, utils, app):
|
||||
|
||||
@ -116,7 +116,9 @@ class Form:
|
||||
for key, value in values.items():
|
||||
if key in filled:
|
||||
del filled[key]
|
||||
if type(value) is list:
|
||||
if value is None:
|
||||
continue
|
||||
elif type(value) is list:
|
||||
filled.setlist(key, value)
|
||||
else:
|
||||
filled.add(key, value)
|
||||
|
||||
@ -326,6 +326,31 @@ class Seeder(object):
|
||||
|
||||
return date_definition
|
||||
|
||||
def add_event_date_definition(
|
||||
self, event_id, start=None, end=None, allday=False, recurrence_rule=""
|
||||
):
|
||||
from project.models import Event
|
||||
from project.services.event import update_event
|
||||
|
||||
with self._app.app_context():
|
||||
event = Event.query.get(event_id)
|
||||
|
||||
date_definition = self.create_event_date_definition(
|
||||
start, end, allday, recurrence_rule
|
||||
)
|
||||
date_definition.event = event
|
||||
self._db.session.add(date_definition)
|
||||
|
||||
date_definitions = event.date_definitions
|
||||
date_definitions.append(date_definition)
|
||||
event.date_definitions = date_definitions
|
||||
update_event(event)
|
||||
self._db.session.commit()
|
||||
|
||||
date_definition_id = date_definition.id
|
||||
|
||||
return date_definition_id
|
||||
|
||||
def create_event_unverified(self):
|
||||
user_id = self.create_user("unverified@test.de")
|
||||
admin_unit_id = self.create_admin_unit(user_id, "Unverified Crew")
|
||||
|
||||
@ -53,8 +53,8 @@ def test_read_co_organizers(seeder, utils):
|
||||
utils.assert_response_contains(response, "Organizer B")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("db_error", [True, False])
|
||||
def test_create(client, app, utils, seeder, mocker, db_error):
|
||||
@pytest.mark.parametrize("variant", ["normal", "db_error", "two_date_definitions"])
|
||||
def test_create(client, app, utils, seeder, mocker, variant):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
place_id = seeder.upsert_default_event_place(admin_unit_id)
|
||||
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
|
||||
@ -62,23 +62,28 @@ def test_create(client, app, utils, seeder, mocker, db_error):
|
||||
url = utils.get_url("event_create_for_admin_unit_id", id=admin_unit_id)
|
||||
response = utils.get_ok(url)
|
||||
|
||||
if db_error:
|
||||
if variant == "db_error":
|
||||
utils.mock_db_commit(mocker, UniqueViolation("MockException", "MockException"))
|
||||
|
||||
response = utils.post_form(
|
||||
url,
|
||||
response,
|
||||
{
|
||||
data = {
|
||||
"name": "Name",
|
||||
"description": "Beschreibung",
|
||||
"date_definitions-0-start": ["2030-12-31", "23:59"],
|
||||
"event_place_id": place_id,
|
||||
"organizer_id": organizer_id,
|
||||
"photo-image_base64": seeder.get_default_image_upload_base64(),
|
||||
},
|
||||
}
|
||||
|
||||
if variant == "two_date_definitions":
|
||||
data["date_definitions-1-start"] = ["2030-12-31", "14:00"]
|
||||
|
||||
response = utils.post_form(
|
||||
url,
|
||||
response,
|
||||
data,
|
||||
)
|
||||
|
||||
if db_error:
|
||||
if variant == "db_error":
|
||||
utils.assert_response_db_error(response)
|
||||
return
|
||||
|
||||
@ -94,6 +99,11 @@ def test_create(client, app, utils, seeder, mocker, db_error):
|
||||
)
|
||||
assert event is not None
|
||||
|
||||
if variant == "two_date_definitions":
|
||||
assert len(event.date_definitions) == 2
|
||||
else:
|
||||
assert len(event.date_definitions) == 1
|
||||
|
||||
|
||||
def test_create_allday(client, app, utils, seeder):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
@ -494,26 +504,43 @@ def test_actions_withReferenceLink(seeder, utils):
|
||||
assert b"Veranstaltung empfehlen" in response.data
|
||||
|
||||
|
||||
@pytest.mark.parametrize("db_error", [True, False])
|
||||
def test_update(client, seeder, utils, app, mocker, db_error):
|
||||
@pytest.mark.parametrize(
|
||||
"variant", ["normal", "db_error", "add_date_definition", "remove_date_definition"]
|
||||
)
|
||||
def test_update(client, seeder, utils, app, mocker, variant):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
|
||||
if variant == "remove_date_definition":
|
||||
seeder.add_event_date_definition(event_id)
|
||||
|
||||
url = utils.get_url("event_update", event_id=event_id)
|
||||
response = utils.get_ok(url)
|
||||
|
||||
if db_error:
|
||||
if variant == "db_error":
|
||||
utils.mock_db_commit(mocker)
|
||||
|
||||
data = {
|
||||
"name": "Neuer Name",
|
||||
}
|
||||
|
||||
if variant == "add_date_definition":
|
||||
data["date_definitions-1-start"] = ["2030-12-31", "14:00"]
|
||||
|
||||
if variant == "remove_date_definition":
|
||||
data["date_definitions-1-csrf_token"] = None
|
||||
data["date_definitions-1-start"] = None
|
||||
data["date_definitions-1-end"] = None
|
||||
data["date_definitions-1-allday"] = None
|
||||
data["date_definitions-1-recurrence_rule"] = None
|
||||
|
||||
response = utils.post_form(
|
||||
url,
|
||||
response,
|
||||
{
|
||||
"name": "Neuer Name",
|
||||
},
|
||||
data,
|
||||
)
|
||||
|
||||
if db_error:
|
||||
if variant == "db_error":
|
||||
utils.assert_response_db_error(response)
|
||||
return
|
||||
|
||||
@ -531,6 +558,11 @@ def test_update(client, seeder, utils, app, mocker, db_error):
|
||||
)
|
||||
assert event is not None
|
||||
|
||||
if variant == "add_date_definition":
|
||||
assert len(event.date_definitions) == 2
|
||||
else:
|
||||
assert len(event.date_definitions) == 1
|
||||
|
||||
|
||||
def test_update_co_organizers(client, seeder, utils, app):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user