Exemple #1
0
    def event_date_processor():
        def suffix(d):
            return ("th" if 11 <= d <= 13 else {
                1: "st",
                2: "nd",
                3: "rd"
            }.get(d % 10, "th"))

        s = event_start()
        e = event_end()
        assert s.year == e.year
        if s.month == e.month:
            fancy_dates = f"""{s.strftime('%B')}<span style="white-space: nowrap">
                {s.day}<sup>{suffix(s.day)}</sup>&ndash;{e.day}<sup>{suffix(e.day)}</sup>
                {s.year}
                </span>"""

            simple_dates = f"{s.day}&ndash;{e.day} {s.strftime('%B')}"

        else:
            fancy_dates = f"""{s.strftime("%B")}
                {s.day}<sup>{suffix(s.day)}</sup>&ndash;{e.strftime("%B")}
                {e.day}<sup>{suffix(e.day)}</sup>"""

            simple_dates = (
                f"""{s.day} {s.strftime("%B")}&ndash;{e.day} {e.strftime("%B")}"""
            )

        return {
            "fancy_dates": Markup(fancy_dates),
            "simple_dates": Markup(simple_dates),
            "event_start": s,
            "event_end": e,
            "event_year": s.year,
        }
Exemple #2
0
    def get_days_with_slots(cls, now=None):
        remaining_slots = cls.get_remaining_lightning_slots()
        now = datetime.now() if now is None else now

        # If we're before the event start we don't need to worry
        if now < event_start():
            return remaining_slots

        # If the day has passed (or is today) there're no more slots for it
        for (day_name, date) in get_days_map().items():
            if date.date() <= now.date():
                remaining_slots[day_name] = 0

        return remaining_slots
Exemple #3
0
def generate_departure_options():
    choices = []

    # Work out our last arrival based on config
    last_departure = event_end() + timedelta(app.config["DEPARTURE_DAYS"])

    # Work out dates between start of the event and last departure
    choices = generate_day_options(event_start(), last_departure)

    # Replace last array element with the last date and 'or later'
    choices[len(choices) - 1] = (
        last_departure.strftime("%F"),
        last_departure.strftime("%A %-d %B or later"),
    )

    return choices
Exemple #4
0
def generate_arrival_options():
    choices = []

    # Work out our first arrival based on config
    first_arrival = event_start() - timedelta(app.config["ARRIVAL_DAYS"])

    # Work out dates between first arrival and end of the event
    choices = generate_day_options(first_arrival, event_end())

    # Replace first array element with first date and 'or earlier'
    choices[0] = (
        first_arrival.strftime("%F"),
        first_arrival.strftime("%A %-d %B or earlier"),
    )

    return choices
Exemple #5
0
def make_root():
    root = etree.Element("schedule")

    _add_sub_with_text(root, "version", "1.0-public")

    conference = etree.SubElement(root, "conference")

    _add_sub_with_text(conference, "title",
                       "Electromagnetic Field {}".format(event_year()))
    _add_sub_with_text(conference, "acronym", "emf{}".format(event_year()))
    _add_sub_with_text(conference, "start", event_start().strftime("%Y-%m-%d"))
    _add_sub_with_text(conference, "end", event_end().strftime("%Y-%m-%d"))
    _add_sub_with_text(conference, "days", "3")
    _add_sub_with_text(conference, "timeslot_duration", "00:10")

    return root
Exemple #6
0
def sign_up():
    form = VolunteerSignUpForm()
    form.arrival.choices = generate_arrival_options()
    form.departure.choices = generate_departure_options()

    if current_user.is_authenticated and VolunteerUser.get_for_user(
            current_user):
        return redirect(url_for(".account"))

    if request.method != "POST" and current_user.is_authenticated:
        form.volunteer_email.data = current_user.email
        form.nickname.data = current_user.name
        form.volunteer_phone.data = current_user.phone
        # Can't try to process age, as that's only submitted as part of the outreach questions

    if form.validate_on_submit():
        if current_user.is_anonymous:
            create_current_user(form.volunteer_email.data, form.nickname.data)

        new_volunteer = VolunteerUser()
        new_volunteer.user_id = current_user.id
        new_volunteer = update_volunteer_from_form(new_volunteer, form)
        db.session.add(new_volunteer)

        # On sign up give user 'volunteer' permission (+ managers etc.)
        current_user.grant_permission("volunteer:user")

        db.session.commit()
        app.logger.info("Add volunteer: %s", new_volunteer)
        flash("Thank you for signing up!", "message")
        return redirect(url_for(".choose_role"))

    # Set form default arrival and departure dates to be start and end
    form.arrival.data = event_start().strftime("%F")
    form.departure.data = event_end().strftime("%F")

    return render_template("volunteer/sign-up.html",
                           user=current_user,
                           form=form)
Exemple #7
0
    def refresh(self):
        request = requests.get(self.url)

        cal = Calendar.from_ical(request.text)
        if self.name is None:
            self.name = cal.get("X-WR-CALNAME")

        for event in self.events:
            event.displayed = False

        local_tz = pendulum.timezone("Europe/London")
        alerts = []
        uids_seen = set()
        out_of_range_event = False
        for component in cal.walk():
            if component.name == "VEVENT":
                summary = component.get("Summary")

                # postgres converts to UTC if given an aware datetime, so strip it up front
                start_dt = pendulum.instance(component.get("dtstart").dt)
                start_dt = local_tz.convert(start_dt).naive()

                end_dt = pendulum.instance(component.get("dtend").dt)
                end_dt = local_tz.convert(end_dt).naive()

                name = summary
                if summary and start_dt:
                    name = "'{}' at {}".format(summary, start_dt)
                elif summary:
                    name = "'{}'".format(summary)
                elif start_dt:
                    name = "Event at {}".format(start_dt)
                else:
                    name = len(self.events) + 1

                if not component.get("uid"):
                    alerts.append(("danger", "{} has no UID".format(name)))
                    continue

                uid = str(component["uid"])
                if uid in uids_seen:
                    alerts.append(
                        ("danger", "{} has duplicate UID {}".format(name, uid))
                    )
                    continue
                uids_seen.add(uid)

                if "rrule" in component:
                    alerts.append(
                        ("warning", "{} has rrule, which is not processed".format(uid))
                    )

                # Allow a bit of slop for build-up events
                if (
                    start_dt < event_start() - pendulum.duration(days=2)
                    and not out_of_range_event
                ):
                    alerts.append(
                        (
                            "warning",
                            "At least one event ({}) is before the start of the event".format(
                                uid
                            ),
                        )
                    )
                    out_of_range_event = True

                if (
                    end_dt > event_end() + pendulum.duration(days=1)
                    and not out_of_range_event
                ):
                    alerts.append(
                        (
                            "warning",
                            "At least one event ({}) is after the end of the event".format(
                                uid
                            ),
                        )
                    )
                    out_of_range_event = True

                if start_dt > end_dt:
                    alerts.append(
                        (
                            "danger",
                            "Start time for {} is after its end time".format(uid),
                        )
                    )
                    out_of_range_event = True

                try:
                    event = CalendarEvent.query.filter_by(
                        source_id=self.id, uid=uid
                    ).one()

                except NoResultFound:
                    event = CalendarEvent(uid=uid)
                    self.events.append(event)
                    if len(self.events) > 1000:
                        raise Exception("Too many events in feed")

                event.start_dt = start_dt
                event.end_dt = end_dt
                event.summary = component.get("summary")
                event.description = component.get("description")
                event.location = component.get("location")
                event.displayed = True

        self.refreshed_at = pendulum.now()

        return alerts
Exemple #8
0
def get_days_map():
    event_days = [
        datetime.combine(event_start() + timedelta(days=day_idx), time.min)
        for day_idx in range((event_end() - event_start()).days + 1)
    ]
    return {ed.strftime("%a").lower(): ed for ed in event_days}