From 5a053cdcd6b88f9d19b50785626fbca74ddf8792 Mon Sep 17 00:00:00 2001
From: Hayden <64056131+hay-kot@users.noreply.github.com>
Date: Fri, 17 Jun 2022 13:25:47 -0800
Subject: [PATCH] feat: mealplan-webhooks (#1403)
* fix type errors on event bus
* webhooks fields required for new implementation
* db migration
* wip: webhook query + tests and stub function
* ignore type checker error
* type and method cleanup
* datetime and time utc validator
* update testing code for utc scheduled time
* fix file cmp function call
* update version_number
* add support for translating "time" objects when restoring backup
* bump recipe-scrapers
* use specific import syntax
* generate frontend types
* utilize names exports
* use utc times
* add task to scheduler
* implement new scheduler functionality
* stub for type annotation
* implement meal-plan data getter
* add experimental banner
---
....34_f30cf048c228_add_new_webhook_fields.py | 31 +++++++
.../Domain/Group/GroupWebhookEditor.vue | 84 +++++++++++++++++++
frontend/composables/use-group-webhooks.ts | 41 ++++++++-
frontend/pages/group/webhooks.vue | 62 +++++++-------
frontend/types/api-types/group.ts | 10 ++-
frontend/types/components.d.ts | 2 +
mealie/app.py | 4 +
mealie/db/models/group/webhooks.py | 13 ++-
mealie/repos/repository_meals.py | 3 +
mealie/schema/group/__init__.py | 2 +-
mealie/schema/group/webhook.py | 40 ++++++++-
.../services/backups_v2/alchemy_exporter.py | 9 +-
.../event_bus_service/event_bus_service.py | 4 +-
mealie/services/scheduler/tasks/__init__.py | 14 +++-
.../services/scheduler/tasks/post_webhooks.py | 54 ++++++++++++
poetry.lock | 8 +-
pyproject.toml | 2 +-
tests/conftest.py | 16 ++--
.../user_group_tests/test_group_webhooks.py | 53 ++++++------
.../backup_v2_tests/test_alchemy_exporter.py | 2 +-
.../backup_v2_tests/test_backup_v2.py | 2 +-
.../scheduler/tasks/test_post_webhook.py | 65 ++++++++++++++
22 files changed, 428 insertions(+), 93 deletions(-)
create mode 100644 alembic/versions/2022-06-15-21.05.34_f30cf048c228_add_new_webhook_fields.py
create mode 100644 frontend/components/Domain/Group/GroupWebhookEditor.vue
create mode 100644 mealie/services/scheduler/tasks/post_webhooks.py
create mode 100644 tests/unit_tests/services_tests/scheduler/tasks/test_post_webhook.py
diff --git a/alembic/versions/2022-06-15-21.05.34_f30cf048c228_add_new_webhook_fields.py b/alembic/versions/2022-06-15-21.05.34_f30cf048c228_add_new_webhook_fields.py
new file mode 100644
index 000000000000..5b1d029a1721
--- /dev/null
+++ b/alembic/versions/2022-06-15-21.05.34_f30cf048c228_add_new_webhook_fields.py
@@ -0,0 +1,31 @@
+"""add new webhook fields
+
+
+Revision ID: f30cf048c228
+Revises: ab0bae02578f
+Create Date: 2022-06-15 21:05:34.851857
+
+"""
+import sqlalchemy as sa
+
+from alembic import op
+
+# revision identifiers, used by Alembic.
+revision = "f30cf048c228"
+down_revision = "ab0bae02578f"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.add_column("webhook_urls", sa.Column("webhook_type", sa.String(), nullable=True))
+ op.add_column("webhook_urls", sa.Column("scheduled_time", sa.Time(), nullable=True))
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ op.drop_column("webhook_urls", "scheduled_time")
+ op.drop_column("webhook_urls", "webhook_type")
+ # ### end Alembic commands ###
diff --git a/frontend/components/Domain/Group/GroupWebhookEditor.vue b/frontend/components/Domain/Group/GroupWebhookEditor.vue
new file mode 100644
index 000000000000..b276fd032355
--- /dev/null
+++ b/frontend/components/Domain/Group/GroupWebhookEditor.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/composables/use-group-webhooks.ts b/frontend/composables/use-group-webhooks.ts
index 7e7e2abcbd34..12fcc3493b49 100644
--- a/frontend/composables/use-group-webhooks.ts
+++ b/frontend/composables/use-group-webhooks.ts
@@ -37,7 +37,7 @@ export const useGroupWebhooks = function () {
enabled: false,
name: "New Webhook",
url: "",
- time: "00:00",
+ scheduledTime: "00:00",
};
const { data } = await api.groupWebhooks.createOne(payload);
@@ -52,8 +52,23 @@ export const useGroupWebhooks = function () {
return;
}
+ // Convert to UTC time
+ const [hours, minutes] = updateData.scheduledTime.split(":");
+
+ const newDt = new Date();
+ newDt.setHours(Number(hours));
+ newDt.setMinutes(Number(minutes));
+
+ updateData.scheduledTime = `${pad(newDt.getUTCHours(), 2)}:${pad(newDt.getUTCMinutes(), 2)}`;
+ console.log(updateData.scheduledTime);
+
+ const payload = {
+ ...updateData,
+ scheduledTime: updateData.scheduledTime,
+ };
+
loading.value = true;
- const { data } = await api.groupWebhooks.updateOne(updateData.id, updateData);
+ const { data } = await api.groupWebhooks.updateOne(updateData.id, payload);
if (data) {
this.refreshAll();
}
@@ -73,3 +88,25 @@ export const useGroupWebhooks = function () {
return { webhooks, actions, validForm };
};
+
+function pad(num: number, size: number) {
+ let numStr = num.toString();
+ while (numStr.length < size) numStr = "0" + numStr;
+ return numStr;
+}
+
+export function timeUTCToLocal(time: string): string {
+ const [hours, minutes] = time.split(":");
+ const dt = new Date();
+ dt.setUTCMinutes(Number(minutes));
+ dt.setUTCHours(Number(hours));
+ return `${pad(dt.getHours(), 2)}:${pad(dt.getMinutes(), 2)}`;
+}
+
+export function timeLocalToUTC(time: string) {
+ const [hours, minutes] = time.split(":");
+ const dt = new Date();
+ dt.setHours(Number(hours));
+ dt.setMinutes(Number(minutes));
+ return `${pad(dt.getUTCHours(), 2)}:${pad(dt.getUTCMinutes(), 2)}`;
+}
diff --git a/frontend/pages/group/webhooks.vue b/frontend/pages/group/webhooks.vue
index c631fbb97578..2bbf3b6b479f 100644
--- a/frontend/pages/group/webhooks.vue
+++ b/frontend/pages/group/webhooks.vue
@@ -5,10 +5,16 @@
Webhooks
- The webhooks defined below will be executed when a meal is defined for the day. At the scheduled time the webhooks
- will be sent with the data from the recipe that is scheduled for the day
+
+ The webhooks defined below will be executed when a meal is defined for the day. At the scheduled time the
+ webhooks will be sent with the data from the recipe that is scheduled for the day. Note that webhook execution
+ is not exact. The webhooks are executed on a 5 minutes interval so the webhooks will be executed within 5 +/-
+ minutes of the scheduled.
+
+
+
@@ -17,7 +23,7 @@
{{ $globals.icons.webhook }}
- {{ webhook.name }} - {{ webhook.time }}
+ {{ webhook.name }} - {{ timeDisplay(timeUTCToLocal(webhook.scheduledTime)) }}
@@ -28,35 +34,12 @@
-
-
-
-
-
-
-
-
-
+
@@ -65,15 +48,28 @@