From 65a5d2b6191490b3264dc7c6e6729141d6db7926 Mon Sep 17 00:00:00 2001 From: Jan Peterka Date: Sun, 23 Jul 2023 00:11:40 +0200 Subject: [PATCH] Enhance event duplication (#547) * Add feedback on event deletion * Make event duplication methods accept kwargs * Add EventDuplication controller * Add action_badge to duplication --- app/controllers/__init__.py | 4 +- app/controllers/events/event_duplications.py | 40 ++++++++++++++++++++ app/controllers/events/events.py | 5 ++- app/models/daily_plans.py | 5 ++- app/models/events.py | 17 +++++---- app/presenters/events.py | 5 ++- app/templates/event_duplications/new.html.j2 | 30 +++++++++++++++ app/templates/events/_other_options.html.j2 | 6 +-- app/templates/events/new.html.j2 | 8 ++-- 9 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 app/controllers/events/event_duplications.py create mode 100644 app/templates/event_duplications/new.html.j2 diff --git a/app/controllers/__init__.py b/app/controllers/__init__.py index 4e2681f8..9d8d4ff7 100644 --- a/app/controllers/__init__.py +++ b/app/controllers/__init__.py @@ -8,10 +8,10 @@ from .exports.event_cookbook_exporter import EventCookbookExporterView from .exports.event_timetable_exporter import EventTimetableExporterView - from .events.events import EventView from .events.share_events import ShareEventView from .events.published_events import PublishedEventView +from .events.event_duplications import EventDuplicationView from .event_portion_types import EventPortionTypeView from .errors import ErrorView @@ -53,6 +53,7 @@ "EventView", "EventCookbookExporterView", "EventTimetableExporterView", + "EventDuplicationView", "EventPortionTypeView", "ShareEventView", "PublishedEventView", @@ -100,6 +101,7 @@ def register_all_controllers(application): EventExporterView.register(application, base_class=HelperFlaskView) EventCookbookExporterView.register(application, base_class=HelperFlaskView) EventTimetableExporterView.register(application, base_class=HelperFlaskView) + EventDuplicationView.register(application, base_class=HelperFlaskView) ErrorView.register(application) SupportView.register(application) diff --git a/app/controllers/events/event_duplications.py b/app/controllers/events/event_duplications.py new file mode 100644 index 00000000..248a2413 --- /dev/null +++ b/app/controllers/events/event_duplications.py @@ -0,0 +1,40 @@ +from flask import redirect, request, flash + +# from flask_classful import route +from flask_security import login_required + +from app.helpers.helper_flask_view import HelperFlaskView + +from app.models import Event +from app.forms import EventForm + + +class EventDuplicationView(HelperFlaskView): + decorators = [login_required] + + def before_request(self, name, id): + self.event = Event.load(id) + + def before_new(self, id): + self.validate_show(self.event) + + def before_post(self, id): + self.validate_show(self.event) + + def new(self, id): + self.form = EventForm(obj=self.event) + + return self.template() + + def post(self, id): + form = EventForm(request.form) + + event = self.event.duplicate( + date_from=form.date_from.data, + name=form.name.data, + people_count=form.people_count.data, + ) + + flash("událost byla úspěšně zkopírována.", "success") + + return redirect(event.url) diff --git a/app/controllers/events/events.py b/app/controllers/events/events.py index 1183ebaf..2c042a25 100644 --- a/app/controllers/events/events.py +++ b/app/controllers/events/events.py @@ -108,7 +108,10 @@ def update(self, id): @route("events/delete/", methods=["POST"]) def delete(self, id): - self.event.delete() + if self.event.delete(): + flash("událost smazána", "success") + else: + flash("událost nebyla smazána", "error") return redirect(url_for("EventView:index")) diff --git a/app/models/daily_plans.py b/app/models/daily_plans.py index b1e35fb4..575641e9 100644 --- a/app/models/daily_plans.py +++ b/app/models/daily_plans.py @@ -61,9 +61,10 @@ def load_active_by_date_and_event(date, event): else: return None - def duplicate(self): + def duplicate(self, event, **kwargs): daily_plan = DailyPlan() - daily_plan.date = self.date + daily_plan.date = kwargs.get("date", self.date) + daily_plan.event_id = event.id daily_plan.save() diff --git a/app/models/events.py b/app/models/events.py index ee1fc0d9..6322c025 100644 --- a/app/models/events.py +++ b/app/models/events.py @@ -37,23 +37,24 @@ class Event(BaseModel, BaseMixin, Loggable, Attendable, Collaborative, EventPres cascade="all, delete", ) - def duplicate(self): + def duplicate(self, **kwargs): event = Event() - event.name = f"{self.name} (kopie)" - event.date_from = self.date_from - event.date_to = self.date_to + event.name = kwargs.get("name", f"{self.name} (kopie)") + event.date_from = kwargs.get("date_from", self.date_from) - event.people_count = self.people_count + start_date_offset = (event.date_from - self.date_from).days + event.date_to = self.date_to + timedelta(days=start_date_offset) + + event.people_count = kwargs.get("people_count", self.people_count) event.daily_plans = [] event.save() for old_plan in self.daily_plans: - plan = old_plan.duplicate() - plan.event_id = event.id - plan.edit() + offset_date = old_plan.date + timedelta(days=start_date_offset) + old_plan.duplicate(date=offset_date, event=event) return event diff --git a/app/presenters/events.py b/app/presenters/events.py index f08212a0..9ad666a4 100644 --- a/app/presenters/events.py +++ b/app/presenters/events.py @@ -2,7 +2,10 @@ class EventPresenter(ItemPresenter): - LINK_INFO = {"new": {"value": "přidat akci"}} + LINK_INFO = { + "new": {"value": "přidat akci"}, + "duplicate": {"value": "kopírovat akci", "icon": "duplicate"}, + } @property def duration_label(self) -> str: diff --git a/app/templates/event_duplications/new.html.j2 b/app/templates/event_duplications/new.html.j2 new file mode 100644 index 00000000..49f76e79 --- /dev/null +++ b/app/templates/event_duplications/new.html.j2 @@ -0,0 +1,30 @@ +{% extends "base/base.html.j2" %} +{% block title %} zkopírovat akce {% endblock %} + +{% block content %} + +

zkopírovat akci {{link_to(event)}}

+ +
+ {{ form.hidden_tag() }} + + {{ render_floating_field(form.name, class="mb-2") }} + +
+
+
+
{{ render_floating_field(form.date_from) }}
+ ##
{{ render_floating_field(form.date_to, disabled=True) }}
+
+ +
+
+ {{ render_floating_field(form.people_count, class="mb-2") }} +
+
+ + {{ render_field(form.submit, value="zkopírovat akci") }} +
+ +{% endblock %} + diff --git a/app/templates/events/_other_options.html.j2 b/app/templates/events/_other_options.html.j2 index 0335ccf4..6f4e156a 100644 --- a/app/templates/events/_other_options.html.j2 +++ b/app/templates/events/_other_options.html.j2 @@ -1,11 +1,11 @@ -
+
další akce
- {{ button_to(url_for('EventView:duplicate', id=event.id), - class="btn bg-color-secondary-action color-white w-100", value="zkopírovat " + icon('duplicate')) }} + {{ action_badge("duplicate", event, path=url_for("EventDuplicationView:new", id=event.id), class="w-100") }} +
diff --git a/app/templates/events/new.html.j2 b/app/templates/events/new.html.j2 index c5bffb41..ea7cb07b 100644 --- a/app/templates/events/new.html.j2 +++ b/app/templates/events/new.html.j2 @@ -3,8 +3,8 @@ {% block content %} -
- {{ form.csrf_token }} + + {{ form.hidden_tag() }} {{ render_floating_field(form.name, class="mb-2", placeholder="např. Tábor 2023") }} @@ -14,16 +14,14 @@
{{ render_floating_field(form.date_from) }}
{{ render_floating_field(form.date_to) }}
- -
+
{{ render_floating_field(form.people_count, class="mb-2", placeholder="základní, u jednotlivých jídel je možné změnit") }}
- {{ render_field(form.submit) }}