mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
iCal for organization #393
This commit is contained in:
parent
a2269a9123
commit
bfd0a8c24c
@ -296,3 +296,28 @@ def get_admin_unit_organization_invitations_query(email):
|
||||
|
||||
def get_admin_unit_organization_invitations(email):
|
||||
return get_admin_unit_organization_invitations_query(email).all()
|
||||
|
||||
|
||||
def create_ical_events_for_admin_unit(
|
||||
admin_unit: AdminUnit,
|
||||
) -> list: # list[icalendar.Event]
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from project.dateutils import get_today
|
||||
from project.services.event import create_ical_events_for_event, get_events_query
|
||||
from project.services.event_search import EventSearchParams
|
||||
|
||||
result = list()
|
||||
|
||||
params = EventSearchParams()
|
||||
params.date_from = get_today() - relativedelta(months=1)
|
||||
params.admin_unit_id = admin_unit.id
|
||||
params.can_read_private_events = False
|
||||
|
||||
events = get_events_query(params).all()
|
||||
|
||||
for event in events:
|
||||
ical_events = create_ical_events_for_event(event)
|
||||
result.extend(ical_events)
|
||||
|
||||
return result
|
||||
|
||||
@ -24,6 +24,7 @@ from project.models import (
|
||||
EventAttendanceMode,
|
||||
EventCategory,
|
||||
EventDate,
|
||||
EventDateDefinition,
|
||||
EventList,
|
||||
EventOrganizer,
|
||||
EventPlace,
|
||||
@ -461,45 +462,109 @@ def get_meta_data(event: Event, event_date: EventDate = None) -> dict:
|
||||
return meta
|
||||
|
||||
|
||||
def create_ical_event_for_date(event_date: EventDate) -> icalendar.Event:
|
||||
url = url_for("event_date", id=event_date.id, _external=True)
|
||||
def populate_ical_event_with_event(ical_event: icalendar.Event, model_event: Event):
|
||||
ical_event.add("summary", model_event.name)
|
||||
|
||||
event = icalendar.Event()
|
||||
event.add("summary", event_date.event.name)
|
||||
event.add("url", url)
|
||||
event.add("description", url)
|
||||
event.add("uid", url)
|
||||
if model_event.description:
|
||||
desc_short = truncate(model_event.description, 300)
|
||||
ical_event.add("description", desc_short)
|
||||
|
||||
start = event_date.start.astimezone(berlin_tz)
|
||||
if model_event.created_at:
|
||||
ical_event.add("dtstamp", model_event.created_at)
|
||||
|
||||
if event_date.allday:
|
||||
event.add("dtstart", icalendar.vDate(start))
|
||||
else:
|
||||
event.add("dtstart", start)
|
||||
if model_event.updated_at:
|
||||
ical_event.add("last-modified", model_event.updated_at)
|
||||
|
||||
if event_date.end and event_date.end > event_date.start:
|
||||
end = event_date.end.astimezone(berlin_tz)
|
||||
|
||||
if event_date.allday:
|
||||
if not date_parts_are_equal(start, end):
|
||||
next_day = round_to_next_day(end)
|
||||
event.add("dtend", icalendar.vDate(next_day))
|
||||
else:
|
||||
event.add("dtend", end)
|
||||
|
||||
if event_date.event.created_at:
|
||||
event.add("dtstamp", event_date.event.created_at)
|
||||
|
||||
if event_date.event.updated_at:
|
||||
event.add("last-modified", event_date.event.updated_at)
|
||||
if model_event.status and model_event.status == EventStatus.cancelled:
|
||||
ical_event.add("status", "CANCELLED")
|
||||
|
||||
if (
|
||||
event_date.event.attendance_mode
|
||||
and event_date.event.attendance_mode != EventAttendanceMode.online
|
||||
model_event.attendance_mode
|
||||
and model_event.attendance_mode != EventAttendanceMode.online
|
||||
and model_event.event_place
|
||||
):
|
||||
event.add("location", get_place_str(event_date.event.event_place))
|
||||
place = model_event.event_place
|
||||
place_str = get_place_str(place)
|
||||
ical_event.add("location", place_str)
|
||||
|
||||
return event
|
||||
location = place.location
|
||||
if location and location.coordinate:
|
||||
ical_event.add("geo", (location.latitude, location.longitude))
|
||||
ical_event.add(
|
||||
"X-APPLE-STRUCTURED-LOCATION",
|
||||
f"geo:{location.latitude},{location.longitude}",
|
||||
parameters={
|
||||
"VALUE": "URI",
|
||||
"X-ADDRESS": place_str, # must be same as "location"
|
||||
"X-APPLE-RADIUS": "100",
|
||||
"X-TITLE": place_str, # must be same as "location"
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def populate_ical_event_with_datish(
|
||||
ical_event: icalendar.Event, datish, recurrence_rule: str = None
|
||||
):
|
||||
# datish: EventDate|EventDateDefinition
|
||||
start = datish.start.astimezone(berlin_tz)
|
||||
|
||||
if datish.allday:
|
||||
ical_event.add("dtstart", icalendar.vDate(start))
|
||||
else:
|
||||
ical_event.add("dtstart", start)
|
||||
|
||||
if recurrence_rule:
|
||||
ical_event.add(
|
||||
"rrule", icalendar.vRecur.from_ical(recurrence_rule.replace("RRULE:", ""))
|
||||
)
|
||||
|
||||
if datish.end and datish.end > datish.start:
|
||||
end = datish.end.astimezone(berlin_tz)
|
||||
|
||||
if datish.allday:
|
||||
if not date_parts_are_equal(start, end):
|
||||
next_day = round_to_next_day(end)
|
||||
ical_event.add("dtend", icalendar.vDate(next_day))
|
||||
else:
|
||||
ical_event.add("dtend", end)
|
||||
|
||||
|
||||
def create_ical_event_for_date(event_date: EventDate) -> icalendar.Event:
|
||||
ical_event = icalendar.Event()
|
||||
populate_ical_event_with_event(ical_event, event_date.event)
|
||||
populate_ical_event_with_datish(ical_event, event_date)
|
||||
|
||||
url = url_for("event_date", id=event_date.id, _external=True)
|
||||
ical_event.add("url", url)
|
||||
ical_event.add("uid", url)
|
||||
|
||||
return ical_event
|
||||
|
||||
|
||||
def create_ical_event_for_date_definition(
|
||||
date_definition: EventDateDefinition,
|
||||
) -> icalendar.Event:
|
||||
ical_event = icalendar.Event()
|
||||
populate_ical_event_with_event(ical_event, date_definition.event)
|
||||
populate_ical_event_with_datish(
|
||||
ical_event, date_definition, date_definition.recurrence_rule
|
||||
)
|
||||
|
||||
url = url_for("event", event_id=date_definition.event.id, _external=True)
|
||||
ical_event.add("url", url)
|
||||
ical_event.add("uid", f"{url}#{date_definition.id}")
|
||||
|
||||
return ical_event
|
||||
|
||||
|
||||
def create_ical_events_for_event(event: Event) -> list: # list[icalendar.Event]
|
||||
result = list()
|
||||
|
||||
for date_definition in event.date_definitions:
|
||||
ical_event = create_ical_event_for_date_definition(date_definition)
|
||||
result.append(ical_event)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def update_recurring_dates():
|
||||
|
||||
@ -38,6 +38,24 @@ const OrganizationRead = {
|
||||
<template v-if="organization.location.street">{{ organization.location.street }}, </template>
|
||||
{{ organization.location.postalCode }} {{ organization.location.city }}
|
||||
</div>
|
||||
|
||||
<b-button v-b-modal.modal-ical variant="outline-secondary" class="mt-4">
|
||||
<i class="fa fa-fw fa-calendar"></i>
|
||||
{{ $t("comp.icalExport") }}
|
||||
</b-button>
|
||||
|
||||
<b-modal id="modal-ical" :title="$t('comp.icalExport')" size="lg" ok-only>
|
||||
<template #default="{ hide }">
|
||||
<b-input-group class="mb-3">
|
||||
<b-form-input :value="icalUrl" ref="icalInput"></b-form-input>
|
||||
</b-input-group>
|
||||
</template>
|
||||
<template #modal-footer="{ ok, cancel, hide }">
|
||||
<b-button variant="primary" @click.prevent="copyIcal()">{{ $t('comp.copy') }}</b-button>
|
||||
<b-button variant="secondary" :href="icalUrl">{{ $t('comp.download') }}</b-button>
|
||||
<b-button variant="outline-secondary" @click="hide()">{{ $t("shared.close") }}</b-button>
|
||||
</template>
|
||||
</b-modal>
|
||||
</b-col>
|
||||
</b-row>
|
||||
|
||||
@ -48,6 +66,26 @@ const OrganizationRead = {
|
||||
</b-overlay>
|
||||
</div>
|
||||
`,
|
||||
i18n: {
|
||||
messages: {
|
||||
en: {
|
||||
comp: {
|
||||
copy: "Copy link",
|
||||
download: "Download",
|
||||
icalCopied: "Link copied",
|
||||
icalExport: "iCal calendar",
|
||||
},
|
||||
},
|
||||
de: {
|
||||
comp: {
|
||||
copy: "Link kopieren",
|
||||
download: "Runterladen",
|
||||
icalCopied: "Link kopiert",
|
||||
icalExport: "iCal Kalender",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
data: () => ({
|
||||
isLoading: false,
|
||||
organization: null,
|
||||
@ -56,6 +94,9 @@ const OrganizationRead = {
|
||||
organizationId() {
|
||||
return this.$route.params.organization_id;
|
||||
},
|
||||
icalUrl() {
|
||||
return `${window.location.origin}/organizations/${this.organizationId}/ical`;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.isLoading = false;
|
||||
@ -79,5 +120,10 @@ const OrganizationRead = {
|
||||
handleLoading(isLoading) {
|
||||
this.isLoading = isLoading;
|
||||
},
|
||||
copyIcal() {
|
||||
this.$refs.icalInput.select();
|
||||
document.execCommand("copy");
|
||||
this.$root.makeSuccessToast(this.$t("comp.icalCopied"))
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@ -1513,7 +1513,9 @@ $('#allday').on('change', function() {
|
||||
<div class="modal-body">
|
||||
<div class="list-group">
|
||||
<a class="list-group-item list-group-item-action" href="{{ calendar_links["ics"] }}"><i class="fab fa-microsoft"></i> Outlook</a>
|
||||
{% if "google" in calendar_links %}
|
||||
<a class="list-group-item list-group-item-action" href="{{ calendar_links["google"] }}" target="_blank" rel="noopener noreferrer"><i class="fab fa-google"></i> {{ _('Google calendar') }}</a>
|
||||
{% endif %}
|
||||
<a class="list-group-item list-group-item-action" href="{{ calendar_links["ics"] }}"><i class="fab fa-apple"></i> {{ _('Apple calendar') }}</a>
|
||||
<a class="list-group-item list-group-item-action" href="{{ calendar_links["ics"] }}"><i class="fab fa-yahoo"></i> {{ _('Yahoo calendar') }}</a>
|
||||
<a class="list-group-item list-group-item-action" href="{{ calendar_links["ics"] }}"><i class="fa fa-calendar"></i> {{ _('Other calendar') }}</a>
|
||||
|
||||
@ -9,6 +9,6 @@
|
||||
{% block content_container_attribs %}{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
{{ render_event_props_seo(event, event.min_start_definition.start, event.min_start_definition.end, event.min_start_definition.allday, dates, user_rights['can_update_event'], user_rights=user_rights, share_links=share_links, current_user=current_user) }}
|
||||
{{ render_event_props_seo(event, event.min_start_definition.start, event.min_start_definition.end, event.min_start_definition.allday, dates, user_rights['can_update_event'], user_rights=user_rights, share_links=share_links, calendar_links=calendar_links, current_user=current_user) }}
|
||||
|
||||
{% endblock %}
|
||||
@ -105,6 +105,7 @@
|
||||
},
|
||||
},
|
||||
cancel: "Cancel",
|
||||
close: "Close",
|
||||
decline: "Decline",
|
||||
save: "Save",
|
||||
submit: "Submit",
|
||||
@ -216,6 +217,7 @@
|
||||
},
|
||||
},
|
||||
cancel: "Abbrechen",
|
||||
close: "Schließen",
|
||||
decline: "Ablehnen",
|
||||
save: "Speichern",
|
||||
submit: "Senden",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from flask import flash, jsonify, redirect, render_template, request, url_for
|
||||
from flask import Response, flash, jsonify, redirect, render_template, request, url_for
|
||||
from flask_babelex import gettext
|
||||
from flask_security import auth_required, current_user
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
@ -15,7 +15,7 @@ from project.access import (
|
||||
get_admin_unit_members_with_permission,
|
||||
has_access,
|
||||
)
|
||||
from project.dateutils import get_next_full_hour
|
||||
from project.dateutils import create_icalendar, get_next_full_hour
|
||||
from project.forms.event import CreateEventForm, DeleteEventForm, UpdateEventForm
|
||||
from project.jsonld import DateTimeEncoder, get_sd_for_event_date
|
||||
from project.models import (
|
||||
@ -30,6 +30,7 @@ from project.models import (
|
||||
PublicStatus,
|
||||
)
|
||||
from project.services.event import (
|
||||
create_ical_events_for_event,
|
||||
get_event_with_details_or_404,
|
||||
get_meta_data,
|
||||
get_significant_event_changes,
|
||||
@ -43,6 +44,7 @@ from project.views.event_suggestion import send_event_suggestion_review_status_m
|
||||
from project.views.utils import (
|
||||
flash_errors,
|
||||
flash_message,
|
||||
get_calendar_links_for_event,
|
||||
get_share_links,
|
||||
handleSqlError,
|
||||
send_mails,
|
||||
@ -58,6 +60,7 @@ def event(event_id):
|
||||
dates = get_upcoming_event_dates(event.id)
|
||||
url = url_for("event", event_id=event_id, _external=True)
|
||||
share_links = get_share_links(url, event.name)
|
||||
calendar_links = get_calendar_links_for_event(event)
|
||||
|
||||
structured_datas = list()
|
||||
for event_date in dates:
|
||||
@ -75,6 +78,7 @@ def event(event_id):
|
||||
user_rights=user_rights,
|
||||
canonical_url=url_for("event", event_id=event_id, _external=True),
|
||||
share_links=share_links,
|
||||
calendar_links=calendar_links,
|
||||
)
|
||||
|
||||
|
||||
@ -434,3 +438,21 @@ def send_event_report_mails(event: Event, report: dict):
|
||||
event=event,
|
||||
report=report,
|
||||
)
|
||||
|
||||
|
||||
@app.route("/event/<int:id>/ical")
|
||||
def event_ical(id):
|
||||
event = get_event_with_details_or_404(id)
|
||||
can_read_event_or_401(event)
|
||||
|
||||
ical_events = create_ical_events_for_event(event)
|
||||
|
||||
cal = create_icalendar()
|
||||
for ical_event in ical_events:
|
||||
cal.add_component(ical_event)
|
||||
|
||||
return Response(
|
||||
cal.to_ical(),
|
||||
mimetype="text/calendar",
|
||||
headers={"Content-disposition": f"attachment; filename=event_{id}.ics"},
|
||||
)
|
||||
|
||||
@ -16,7 +16,11 @@ from project.services.event import (
|
||||
)
|
||||
from project.services.event_search import EventSearchParams
|
||||
from project.views.event import get_event_category_choices, get_menu_user_rights
|
||||
from project.views.utils import flash_errors, get_calendar_links, get_share_links
|
||||
from project.views.utils import (
|
||||
flash_errors,
|
||||
get_calendar_links_for_event_date,
|
||||
get_share_links,
|
||||
)
|
||||
|
||||
|
||||
def prepare_event_date_form(form):
|
||||
@ -51,7 +55,7 @@ def event_date(id):
|
||||
|
||||
url = url_for("event_date", id=id, _external=True)
|
||||
share_links = get_share_links(url, event_date.event.name)
|
||||
calendar_links = get_calendar_links(event_date)
|
||||
calendar_links = get_calendar_links_for_event_date(event_date)
|
||||
|
||||
return render_template(
|
||||
"event_date/read.html",
|
||||
|
||||
@ -1,9 +1,30 @@
|
||||
from flask import render_template
|
||||
from flask import Response, render_template
|
||||
|
||||
from project import app
|
||||
from project.dateutils import create_icalendar
|
||||
from project.models import AdminUnit
|
||||
from project.services.admin_unit import create_ical_events_for_admin_unit
|
||||
|
||||
|
||||
@app.route("/organizations")
|
||||
@app.route("/organizations/<path:path>")
|
||||
def organizations(path=None):
|
||||
return render_template("organization/main.html")
|
||||
|
||||
|
||||
@app.route("/organizations/<int:id>/ical")
|
||||
def organization_ical(id):
|
||||
admin_unit = AdminUnit.query.get_or_404(id)
|
||||
|
||||
cal = create_icalendar()
|
||||
cal.add("x-wr-calname", admin_unit.name)
|
||||
ical_events = create_ical_events_for_admin_unit(admin_unit)
|
||||
|
||||
for ical_event in ical_events:
|
||||
cal.add_component(ical_event)
|
||||
|
||||
return Response(
|
||||
cal.to_ical(),
|
||||
mimetype="text/calendar",
|
||||
headers={"Content-disposition": f"attachment; filename=organization_{id}.ics"},
|
||||
)
|
||||
|
||||
@ -12,7 +12,7 @@ from wtforms import FormField
|
||||
from project import app, mail
|
||||
from project.access import get_admin_unit_for_manage, get_admin_units_for_manage
|
||||
from project.dateutils import berlin_tz, round_to_next_day
|
||||
from project.models import EventAttendanceMode, EventDate
|
||||
from project.models import Event, EventAttendanceMode, EventDate
|
||||
from project.utils import get_place_str, strings_are_equal_ignoring_case
|
||||
|
||||
|
||||
@ -197,7 +197,7 @@ def get_share_links(url: str, title: str) -> dict:
|
||||
return share_links
|
||||
|
||||
|
||||
def get_calendar_links(event_date: EventDate) -> dict:
|
||||
def get_calendar_links_for_event_date(event_date: EventDate) -> dict:
|
||||
calendar_links = dict()
|
||||
|
||||
url = url_for("event_date", id=event_date.id, _external=True)
|
||||
@ -234,6 +234,12 @@ def get_calendar_links(event_date: EventDate) -> dict:
|
||||
return calendar_links
|
||||
|
||||
|
||||
def get_calendar_links_for_event(event: Event) -> dict:
|
||||
calendar_links = dict()
|
||||
calendar_links["ics"] = url_for("event_ical", id=event.id, _external=True)
|
||||
return calendar_links
|
||||
|
||||
|
||||
def get_invitation_access_result(email: str):
|
||||
from project.services.user import find_user_by_email
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@ from project.views.event_date import prepare_event_date_form
|
||||
from project.views.utils import (
|
||||
flash_errors,
|
||||
flash_message,
|
||||
get_calendar_links,
|
||||
get_calendar_links_for_event_date,
|
||||
get_pagination_urls,
|
||||
get_share_links,
|
||||
handleSqlError,
|
||||
@ -81,7 +81,7 @@ def widget_event_date(au_short_name, id):
|
||||
|
||||
url = url_for("event_date", id=id, _external=True)
|
||||
share_links = get_share_links(url, event_date.event.name)
|
||||
calendar_links = get_calendar_links(event_date)
|
||||
calendar_links = get_calendar_links_for_event_date(event_date)
|
||||
|
||||
return render_template(
|
||||
"widget/event_date/read.html",
|
||||
|
||||
@ -185,11 +185,15 @@ class Seeder(object):
|
||||
def create_admin_unit_member_event_verifier(self, admin_unit_id):
|
||||
return self.create_admin_unit_member(admin_unit_id, ["event_verifier"])
|
||||
|
||||
def upsert_event_place(self, admin_unit_id, name):
|
||||
def upsert_event_place(self, admin_unit_id, name, location=None):
|
||||
from project.services.place import upsert_event_place
|
||||
|
||||
with self._app.app_context():
|
||||
place = upsert_event_place(admin_unit_id, name)
|
||||
|
||||
if location:
|
||||
place.location = location
|
||||
|
||||
self._db.session.commit()
|
||||
place_id = place.id
|
||||
|
||||
@ -317,6 +321,7 @@ class Seeder(object):
|
||||
co_organizer_ids=None,
|
||||
description="Beschreibung",
|
||||
tags="",
|
||||
place_id=None,
|
||||
):
|
||||
from project.models import (
|
||||
Event,
|
||||
@ -332,7 +337,6 @@ class Seeder(object):
|
||||
event.categories = [upsert_event_category("Other")]
|
||||
event.name = name
|
||||
event.description = description
|
||||
event.event_place_id = self.upsert_default_event_place(admin_unit_id)
|
||||
event.organizer_id = self.upsert_default_event_organizer(admin_unit_id)
|
||||
event.external_link = external_link
|
||||
event.ticket_link = ""
|
||||
@ -340,6 +344,11 @@ class Seeder(object):
|
||||
event.price_info = ""
|
||||
event.attendance_mode = EventAttendanceMode.offline
|
||||
|
||||
if place_id:
|
||||
event.event_place_id = place_id
|
||||
else:
|
||||
event.event_place_id = self.upsert_default_event_place(admin_unit_id)
|
||||
|
||||
date_definition = self.create_event_date_definition(
|
||||
start, end, allday, recurrence_rule
|
||||
)
|
||||
@ -636,7 +645,13 @@ class Seeder(object):
|
||||
)
|
||||
|
||||
def create_common_scenario(self):
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from project.models import Location
|
||||
|
||||
with self._app.app_context():
|
||||
now = self.get_now_by_minute()
|
||||
|
||||
# Admin with eventcally organisation
|
||||
admin_id = self.create_user(
|
||||
"admin@test.de", "MeinPasswortIstDasBeste", admin=True
|
||||
@ -666,6 +681,24 @@ class Seeder(object):
|
||||
verify=True,
|
||||
)
|
||||
self.create_event(marketing_admin_unit_id)
|
||||
self.create_event(
|
||||
marketing_admin_unit_id,
|
||||
recurrence_rule="RRULE:FREQ=DAILY;COUNT=7",
|
||||
name="Recurring",
|
||||
start=now,
|
||||
end=now + relativedelta(hours=1),
|
||||
place_id=self.upsert_event_place(
|
||||
marketing_admin_unit_id,
|
||||
"MachmitHaus",
|
||||
Location(
|
||||
street="Markt 7",
|
||||
postalCode="38640",
|
||||
city="Goslar",
|
||||
latitude=51.9077888,
|
||||
longitude=10.4333312,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# Unverified Verein organisation
|
||||
verein_admin_unit_id = self.create_admin_unit(
|
||||
|
||||
@ -269,3 +269,41 @@ def test_get_events_fulltext(
|
||||
for item in pagination.items:
|
||||
assert item.id == event_ids[order[i]]
|
||||
i = i + 1
|
||||
|
||||
|
||||
def test_create_ical_events_for_event(client, app, db, utils, seeder):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
|
||||
with app.app_context():
|
||||
from project.models import Event, Location
|
||||
from project.services.event import create_ical_events_for_event
|
||||
|
||||
event = Event.query.get(event_id)
|
||||
event.description = "This is a fantastic event. Watch out!"
|
||||
|
||||
place = event.event_place
|
||||
place.name = "MachMitHaus Goslar"
|
||||
|
||||
location = Location()
|
||||
location.street = "Markt 7"
|
||||
location.postalCode = "38640"
|
||||
location.city = "Goslar"
|
||||
location.latitude = 51.9077888
|
||||
location.longitude = 10.4333312
|
||||
place.location = location
|
||||
|
||||
db.session.commit()
|
||||
|
||||
with app.test_request_context():
|
||||
ical_events = create_ical_events_for_event(event)
|
||||
|
||||
assert len(ical_events) == 1
|
||||
|
||||
ical_event = ical_events[0]
|
||||
assert "DESCRIPTION" in ical_event
|
||||
assert "GEO" in ical_event
|
||||
assert "X-APPLE-STRUCTURED-LOCATION" in ical_event
|
||||
|
||||
ical = ical_event.to_ical()
|
||||
assert ical
|
||||
|
||||
@ -649,3 +649,63 @@ def test_report(seeder, utils):
|
||||
|
||||
url = utils.get_url("event_report", event_id=event_id)
|
||||
utils.get_ok(url)
|
||||
|
||||
|
||||
def test_ical(client, seeder, utils):
|
||||
from project.dateutils import create_berlin_date
|
||||
|
||||
user_id, admin_unit_id = seeder.setup_base(log_in=False)
|
||||
|
||||
# Default
|
||||
event_id = seeder.create_event(admin_unit_id, end=seeder.get_now_by_minute())
|
||||
url = utils.get_url("event_ical", id=event_id)
|
||||
utils.get_ok(url)
|
||||
|
||||
# Draft
|
||||
draft_id = seeder.create_event(
|
||||
admin_unit_id,
|
||||
draft=True,
|
||||
start=create_berlin_date(2020, 1, 2, 14, 30),
|
||||
end=create_berlin_date(2020, 1, 3, 14, 30),
|
||||
)
|
||||
url = utils.get_url("event_ical", id=draft_id)
|
||||
response = utils.get(url)
|
||||
utils.assert_response_unauthorized(response)
|
||||
|
||||
utils.login()
|
||||
utils.get_ok(url)
|
||||
|
||||
# Unverified
|
||||
_, _, unverified_id = seeder.create_event_unverified()
|
||||
url = utils.get_url("event_ical", id=unverified_id)
|
||||
response = utils.get(url)
|
||||
utils.assert_response_unauthorized(response)
|
||||
|
||||
# All-day single day
|
||||
allday_id = seeder.create_event(
|
||||
admin_unit_id, allday=True, start=create_berlin_date(2020, 1, 2, 14, 30)
|
||||
)
|
||||
url = utils.get_url("event_ical", id=allday_id)
|
||||
response = utils.get_ok(url)
|
||||
utils.assert_response_contains(response, "DTSTART;VALUE=DATE:20200102")
|
||||
utils.assert_response_contains_not(response, "DTEND;VALUE=DATE:")
|
||||
|
||||
# All-day multiple days
|
||||
allday_id = seeder.create_event(
|
||||
admin_unit_id,
|
||||
allday=True,
|
||||
start=create_berlin_date(2020, 1, 2, 14, 30),
|
||||
end=create_berlin_date(2020, 1, 3, 14, 30),
|
||||
)
|
||||
url = utils.get_url("event_ical", id=allday_id)
|
||||
response = utils.get_ok(url)
|
||||
utils.assert_response_contains(response, "DTSTART;VALUE=DATE:20200102")
|
||||
utils.assert_response_contains(response, "DTEND;VALUE=DATE:20200104")
|
||||
|
||||
# Recurrence rule
|
||||
event_with_recc_id = seeder.create_event(
|
||||
admin_unit_id, recurrence_rule="RRULE:FREQ=DAILY;COUNT=7"
|
||||
)
|
||||
url = utils.get_url("event_ical", id=event_with_recc_id)
|
||||
response = utils.get_ok(url)
|
||||
utils.assert_response_contains(response, "FREQ=DAILY;COUNT=7")
|
||||
|
||||
11
tests/views/test_organization.py
Normal file
11
tests/views/test_organization.py
Normal file
@ -0,0 +1,11 @@
|
||||
def test_organizations(client, seeder, utils):
|
||||
url = utils.get_url("organizations")
|
||||
utils.get_ok(url)
|
||||
|
||||
|
||||
def test_ical(client, seeder, utils):
|
||||
user_id, admin_unit_id = seeder.setup_base(log_in=False)
|
||||
|
||||
seeder.create_event(admin_unit_id, end=seeder.get_now_by_minute())
|
||||
url = utils.get_url("organization_ical", id=admin_unit_id)
|
||||
utils.get_ok(url)
|
||||
@ -12,11 +12,6 @@ def test_up(app, utils):
|
||||
utils.get_ok("up")
|
||||
|
||||
|
||||
def test_organizations(client, seeder, utils):
|
||||
url = utils.get_url("organizations")
|
||||
utils.get_ok(url)
|
||||
|
||||
|
||||
def test_tos(app, db, utils):
|
||||
with app.app_context():
|
||||
from project.services.admin import upsert_settings
|
||||
|
||||
@ -46,7 +46,7 @@ def test_get_calendar_links(client, seeder, utils, app, db, mocker):
|
||||
from project.dateutils import create_berlin_date
|
||||
from project.models import Event, EventAttendanceMode
|
||||
from project.services.event import update_event_dates_with_recurrence_rule
|
||||
from project.views.utils import get_calendar_links
|
||||
from project.views.utils import get_calendar_links_for_event_date
|
||||
|
||||
utils.mock_now(mocker, 2020, 1, 3)
|
||||
|
||||
@ -56,7 +56,7 @@ def test_get_calendar_links(client, seeder, utils, app, db, mocker):
|
||||
date_definition.end = None
|
||||
event.attendance_mode = EventAttendanceMode.online
|
||||
event_date = event.dates[0]
|
||||
links = get_calendar_links(event_date)
|
||||
links = get_calendar_links_for_event_date(event_date)
|
||||
assert "&location" not in links["google"]
|
||||
|
||||
# All-day single day
|
||||
@ -66,7 +66,7 @@ def test_get_calendar_links(client, seeder, utils, app, db, mocker):
|
||||
update_event_dates_with_recurrence_rule(event)
|
||||
db.session.commit()
|
||||
event_date = event.dates[0]
|
||||
links = get_calendar_links(event_date)
|
||||
links = get_calendar_links_for_event_date(event_date)
|
||||
assert "&dates=20200102/20200103&" in links["google"]
|
||||
|
||||
# All-day multiple days
|
||||
@ -76,5 +76,5 @@ def test_get_calendar_links(client, seeder, utils, app, db, mocker):
|
||||
update_event_dates_with_recurrence_rule(event)
|
||||
db.session.commit()
|
||||
event_date = event.dates[0]
|
||||
links = get_calendar_links(event_date)
|
||||
links = get_calendar_links_for_event_date(event_date)
|
||||
assert "&dates=20200102/20200104&" in links["google"]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user