From 4ffc8d1f14fc19cc81d2329cb439f5d6713ba563 Mon Sep 17 00:00:00 2001 From: eikek Date: Mon, 22 Nov 2021 00:22:51 +0100 Subject: [PATCH] Add support for more generic notification This is a start to have different kinds of notifications. It is possible to be notified via e-mail, matrix or gotify. It also extends the current "periodic query" for due items by allowing notification over different channels. A "generic periodic query" variant is added as well. --- .redocly.lint-ignore.yaml | 5 + build.sbt | 97 +- .../docspell/backend/AttachedEvent.scala | 44 + .../scala/docspell/backend/BackendApp.scala | 17 +- .../main/scala/docspell/backend/Config.scala | 8 +- .../scala/docspell/backend/JobFactory.scala | 21 +- .../docspell/backend/MailAddressCodec.scala | 22 + .../scala/docspell/backend/auth/Login.scala | 4 +- .../backend/msg/JobQueuePublish.scala | 31 +- .../docspell/backend/ops/OCustomFields.scala | 32 +- .../scala/docspell/backend/ops/OItem.scala | 240 ++-- .../docspell/backend/ops/ONotification.scala | 347 +++++ .../docspell/backend/ops/OUserTask.scala | 54 +- .../docspell/common/ItemQueryString.scala | 7 + .../scala/docspell/common/LenientUri.scala | 2 + .../main/scala/docspell/common/Logger.scala | 54 +- .../docspell/common/NotifyDueItemsArgs.scala | 2 +- .../scala/docspell/joex/JoexAppImpl.scala | 45 +- .../joex/notify/PeriodicDueItemsTask.scala | 106 ++ .../joex/notify/PeriodicQueryTask.scala | 84 ++ .../docspell/joex/notify/TaskOperations.scala | 64 + .../joex/scheduler/SchedulerBuilder.scala | 11 +- .../joex/scheduler/SchedulerImpl.scala | 14 + .../src/main/resources/joex-openapi.yml | 12 + .../scala/docspell/jsonminiq/Format.scala | 59 + .../docspell/jsonminiq/JsonMiniQuery.scala | 245 ++++ .../scala/docspell/jsonminiq/Parser.scala | 105 ++ .../scala/docspell/jsonminiq/Fixtures.scala | 76 ++ .../scala/docspell/jsonminiq/FormatTest.scala | 52 + .../jsonminiq/JsonMiniQueryTest.scala | 161 +++ .../scala/docspell/jsonminiq/ParserTest.scala | 54 + .../docspell/notification/api/Channel.scala | 112 ++ .../notification/api/ChannelRef.scala | 24 + .../notification/api/ChannelType.scala | 46 + .../docspell/notification/api/Event.scala | 246 ++++ .../notification/api/EventCodec.scala | 23 + .../notification/api/EventContext.scala | 91 ++ .../notification/api/EventExchange.scala | 54 + .../notification/api/EventReader.scala | 17 + .../docspell/notification/api/EventSink.scala | 25 + .../api/NotificationBackend.scala | 89 ++ .../api/NotificationChannel.scala | 41 + .../notification/api/NotificationModule.scala | 62 + .../api/PeriodicDueItemsArgs.scala | 41 + .../notification/api/PeriodicQueryArgs.scala | 38 + .../docspell/notification/api/package.scala | 29 + .../impl/AbstractEventContext.scala | 63 + .../notification/impl/DbEventContext.scala | 41 + .../notification/impl/EmailBackend.scala | 40 + .../notification/impl/EventNotify.scala | 52 + .../impl/ExampleEventContext.scala | 39 + .../notification/impl/GotifyBackend.scala | 49 + .../notification/impl/HttpPostBackend.scala | 36 + .../docspell/notification/impl/HttpSend.scala | 35 + .../docspell/notification/impl/Markdown.scala | 40 + .../notification/impl/MatrixBackend.scala | 45 + .../impl/NotificationBackendImpl.scala | 61 + .../impl/NotificationModuleImpl.scala | 51 + .../notification/impl/context/BasicData.scala | 149 +++ .../impl/context/DeleteFieldValueCtx.scala | 83 ++ .../impl/context/ItemSelectionCtx.scala | 117 ++ .../impl/context/JobDoneCtx.scala | 56 + .../impl/context/JobSubmittedCtx.scala | 57 + .../impl/context/SetFieldValueCtx.scala | 83 ++ .../notification/impl/context/Syntax.scala | 18 + .../impl/context/TagsChangedCtx.scala | 82 ++ .../impl/context/TagsChangedCtxTest.scala | 75 ++ .../src/main/resources/docspell-openapi.yml | 1113 ++++++++++++++++- .../restapi/codec/ChannelEihterCodec.scala | 25 + .../restapi/model/NotificationChannel.scala | 130 ++ .../restapi/model/NotificationHook.scala | 33 + .../model/PeriodicDueItemsSettings.scala | 35 + .../restapi/model/PeriodicQuerySettings.scala | 35 + .../restapi/model/NotificationCodecTest.scala | 62 + .../restserver/src/main/resources/logback.xml | 2 +- .../scala/docspell/restserver/RestApp.scala | 12 + .../docspell/restserver/RestAppImpl.scala | 35 +- .../docspell/restserver/RestServer.scala | 21 +- .../restserver/routes/ItemMultiRoutes.scala | 23 +- .../restserver/routes/ItemRoutes.scala | 33 +- .../routes/NotificationRoutes.scala | 207 +++ .../routes/NotifyDueItemsRoutes.scala | 60 +- .../routes/PeriodicQueryRoutes.scala | 161 +++ .../docspell/restserver/ws/OutputEvent.scala | 1 - .../db/migration/h2/V1.29.1__notification.sql | 62 + .../mariadb/V1.29.1__notification.sql | 62 + .../postgresql/V1.29.1__notification.sql | 62 + .../scala/db/migration/MigrationTasks.scala | 87 ++ .../h2/V1_29_2__MigrateNotifyTask.scala | 23 + .../mariadb/V1_29_2__MigrateNotifyTask.scala | 23 + .../V1_29_2__MigrateNotifyTask.scala | 23 + .../docspell/store/impl/DoobieMeta.scala | 8 + .../store/migrate/FlywayMigrate.scala | 4 +- .../docspell/store/queries/ChannelMap.scala | 44 + .../store/queries/QNotification.scala | 91 ++ .../scala/docspell/store/records/RItem.scala | 8 + .../store/records/RNotificationChannel.scala | 148 +++ .../records/RNotificationChannelGotify.scala | 86 ++ .../records/RNotificationChannelHttp.scala | 75 ++ .../records/RNotificationChannelMail.scala | 88 ++ .../records/RNotificationChannelMatrix.scala | 93 ++ .../store/records/RNotificationHook.scala | 233 ++++ .../records/RNotificationHookEvent.scala | 69 + .../store/records/RPeriodicTask.scala | 13 + .../docspell/store/records/RTagItem.scala | 6 +- .../scala/docspell/store/records/RUser.scala | 3 + .../docspell/store/records/RUserEmail.scala | 12 + .../src/main/scala/docspell/totp/Totp.scala | 4 +- modules/webapp/elm.json | 5 +- modules/webapp/src/main/elm/Api.elm | 209 +++- .../webapp/src/main/elm/Comp/ChannelForm.elm | 280 +++++ .../webapp/src/main/elm/Comp/ChannelMenu.elm | 48 + modules/webapp/src/main/elm/Comp/Dropdown.elm | 21 + ...ificationForm.elm => DueItemsTaskForm.elm} | 233 ++-- ...ificationList.elm => DueItemsTaskList.elm} | 26 +- ...ationManage.elm => DueItemsTaskManage.elm} | 92 +- .../webapp/src/main/elm/Comp/EventSample.elm | 182 +++ .../elm/Comp/ItemDetail/SingleAttachment.elm | 19 +- modules/webapp/src/main/elm/Comp/MenuBar.elm | 17 +- .../main/elm/Comp/NotificationGotifyForm.elm | 117 ++ .../main/elm/Comp/NotificationHookForm.elm | 317 +++++ .../main/elm/Comp/NotificationHookManage.elm | 475 +++++++ .../main/elm/Comp/NotificationHookTable.elm | 106 ++ .../main/elm/Comp/NotificationHttpForm.elm | 99 ++ .../main/elm/Comp/NotificationMailForm.elm | 236 ++++ .../main/elm/Comp/NotificationMatrixForm.elm | 140 +++ .../src/main/elm/Comp/NotificationTest.elm | 146 +++ .../main/elm/Comp/PeriodicQueryTaskForm.elm | 484 +++++++ .../main/elm/Comp/PeriodicQueryTaskList.elm | 102 ++ .../main/elm/Comp/PeriodicQueryTaskManage.elm | 324 +++++ .../src/main/elm/Comp/ScanMailboxManage.elm | 4 +- .../webapp/src/main/elm/Data/ChannelRef.elm | 33 + .../webapp/src/main/elm/Data/ChannelType.elm | 117 ++ .../webapp/src/main/elm/Data/EventType.elm | 90 ++ modules/webapp/src/main/elm/Data/Icons.elm | 37 +- .../src/main/elm/Data/NotificationChannel.elm | 148 +++ .../src/main/elm/Data/NotificationHook.elm | 62 + .../elm/Data/PeriodicDueItemsSettings.elm | 77 ++ .../main/elm/Data/PeriodicQuerySettings.elm | 57 + modules/webapp/src/main/elm/Main.elm | 1 + .../main/elm/Messages/Comp/ChannelForm.elm | 47 + ...ificationForm.elm => DueItemsTaskForm.elm} | 31 +- ...ficationTable.elm => DueItemsTaskList.elm} | 2 +- ...ationManage.elm => DueItemsTaskManage.elm} | 22 +- .../main/elm/Messages/Comp/EventSample.elm | 40 + .../Messages/Comp/NotificationGotifyForm.elm | 37 + .../Messages/Comp/NotificationHookForm.elm | 75 ++ .../Messages/Comp/NotificationHookManage.elm | 106 ++ .../Messages/Comp/NotificationHookTable.elm | 45 + .../Messages/Comp/NotificationHttpForm.elm | 34 + .../Messages/Comp/NotificationMailForm.elm | 49 + .../Messages/Comp/NotificationMatrixForm.elm | 40 + .../Messages/Comp/PeriodicQueryTaskForm.elm | 99 ++ .../Messages/Comp/PeriodicQueryTaskList.elm | 43 + .../Messages/Comp/PeriodicQueryTaskManage.elm | 78 ++ .../main/elm/Messages/Data/ChannelType.elm | 46 + .../src/main/elm/Messages/Data/EventType.elm | 78 ++ .../main/elm/Messages/Page/UserSettings.elm | 83 +- .../src/main/elm/Page/UserSettings/Data.elm | 27 +- .../src/main/elm/Page/UserSettings/Update.elm | 52 +- .../src/main/elm/Page/UserSettings/View2.elm | 206 ++- modules/webapp/src/main/elm/Styles.elm | 7 + project/Dependencies.scala | 16 +- website/site/content/docs/features/_index.md | 5 +- .../site/content/docs/jsonminiquery/_index.md | 258 ++++ .../content/docs/webapp/notification-01.png | Bin 0 -> 10651 bytes .../content/docs/webapp/notification-02.png | Bin 0 -> 33350 bytes .../content/docs/webapp/notification-03.png | Bin 0 -> 14221 bytes .../content/docs/webapp/notification-04.png | Bin 0 -> 187656 bytes .../content/docs/webapp/notification-05.png | Bin 0 -> 235127 bytes .../site/content/docs/webapp/notification.md | 205 +++ .../content/docs/webapp/notify-due-items.jpg | Bin 238293 -> 0 bytes .../content/docs/webapp/notify-due-items.png | Bin 185940 -> 0 bytes .../content/docs/webapp/notifydueitems.md | 2 + website/site/templates/overview.html | 3 + 175 files changed, 13041 insertions(+), 599 deletions(-) create mode 100644 .redocly.lint-ignore.yaml create mode 100644 modules/backend/src/main/scala/docspell/backend/AttachedEvent.scala create mode 100644 modules/backend/src/main/scala/docspell/backend/MailAddressCodec.scala create mode 100644 modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala create mode 100644 modules/joex/src/main/scala/docspell/joex/notify/PeriodicDueItemsTask.scala create mode 100644 modules/joex/src/main/scala/docspell/joex/notify/PeriodicQueryTask.scala create mode 100644 modules/joex/src/main/scala/docspell/joex/notify/TaskOperations.scala create mode 100644 modules/jsonminiq/src/main/scala/docspell/jsonminiq/Format.scala create mode 100644 modules/jsonminiq/src/main/scala/docspell/jsonminiq/JsonMiniQuery.scala create mode 100644 modules/jsonminiq/src/main/scala/docspell/jsonminiq/Parser.scala create mode 100644 modules/jsonminiq/src/test/scala/docspell/jsonminiq/Fixtures.scala create mode 100644 modules/jsonminiq/src/test/scala/docspell/jsonminiq/FormatTest.scala create mode 100644 modules/jsonminiq/src/test/scala/docspell/jsonminiq/JsonMiniQueryTest.scala create mode 100644 modules/jsonminiq/src/test/scala/docspell/jsonminiq/ParserTest.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/ChannelRef.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/ChannelType.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/Event.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/EventCodec.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/EventContext.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/EventExchange.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/EventReader.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/EventSink.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/NotificationBackend.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/NotificationChannel.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/NotificationModule.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/PeriodicDueItemsArgs.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/PeriodicQueryArgs.scala create mode 100644 modules/notification/api/src/main/scala/docspell/notification/api/package.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/AbstractEventContext.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/DbEventContext.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/EmailBackend.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/EventNotify.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/ExampleEventContext.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/GotifyBackend.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/HttpPostBackend.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/HttpSend.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/Markdown.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/MatrixBackend.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationBackendImpl.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationModuleImpl.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/BasicData.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/DeleteFieldValueCtx.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/ItemSelectionCtx.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobDoneCtx.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobSubmittedCtx.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/SetFieldValueCtx.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/Syntax.scala create mode 100644 modules/notification/impl/src/main/scala/docspell/notification/impl/context/TagsChangedCtx.scala create mode 100644 modules/notification/impl/src/test/scala/docspell/notification/impl/context/TagsChangedCtxTest.scala create mode 100644 modules/restapi/src/main/scala/docspell/restapi/codec/ChannelEihterCodec.scala create mode 100644 modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala create mode 100644 modules/restapi/src/main/scala/docspell/restapi/model/NotificationHook.scala create mode 100644 modules/restapi/src/main/scala/docspell/restapi/model/PeriodicDueItemsSettings.scala create mode 100644 modules/restapi/src/main/scala/docspell/restapi/model/PeriodicQuerySettings.scala create mode 100644 modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala create mode 100644 modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala create mode 100644 modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala create mode 100644 modules/store/src/main/resources/db/migration/h2/V1.29.1__notification.sql create mode 100644 modules/store/src/main/resources/db/migration/mariadb/V1.29.1__notification.sql create mode 100644 modules/store/src/main/resources/db/migration/postgresql/V1.29.1__notification.sql create mode 100644 modules/store/src/main/scala/db/migration/MigrationTasks.scala create mode 100644 modules/store/src/main/scala/db/migration/h2/V1_29_2__MigrateNotifyTask.scala create mode 100644 modules/store/src/main/scala/db/migration/mariadb/V1_29_2__MigrateNotifyTask.scala create mode 100644 modules/store/src/main/scala/db/migration/postgresql/V1_29_2__MigrateNotifyTask.scala create mode 100644 modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala create mode 100644 modules/store/src/main/scala/docspell/store/queries/QNotification.scala create mode 100644 modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala create mode 100644 modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala create mode 100644 modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala create mode 100644 modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala create mode 100644 modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala create mode 100644 modules/store/src/main/scala/docspell/store/records/RNotificationHook.scala create mode 100644 modules/store/src/main/scala/docspell/store/records/RNotificationHookEvent.scala create mode 100644 modules/webapp/src/main/elm/Comp/ChannelForm.elm create mode 100644 modules/webapp/src/main/elm/Comp/ChannelMenu.elm rename modules/webapp/src/main/elm/Comp/{NotificationForm.elm => DueItemsTaskForm.elm} (74%) rename modules/webapp/src/main/elm/Comp/{NotificationList.elm => DueItemsTaskList.elm} (74%) rename modules/webapp/src/main/elm/Comp/{NotificationManage.elm => DueItemsTaskManage.elm} (75%) create mode 100644 modules/webapp/src/main/elm/Comp/EventSample.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationHookForm.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationHookManage.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationHookTable.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationHttpForm.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationMailForm.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationMatrixForm.elm create mode 100644 modules/webapp/src/main/elm/Comp/NotificationTest.elm create mode 100644 modules/webapp/src/main/elm/Comp/PeriodicQueryTaskForm.elm create mode 100644 modules/webapp/src/main/elm/Comp/PeriodicQueryTaskList.elm create mode 100644 modules/webapp/src/main/elm/Comp/PeriodicQueryTaskManage.elm create mode 100644 modules/webapp/src/main/elm/Data/ChannelRef.elm create mode 100644 modules/webapp/src/main/elm/Data/ChannelType.elm create mode 100644 modules/webapp/src/main/elm/Data/EventType.elm create mode 100644 modules/webapp/src/main/elm/Data/NotificationChannel.elm create mode 100644 modules/webapp/src/main/elm/Data/NotificationHook.elm create mode 100644 modules/webapp/src/main/elm/Data/PeriodicDueItemsSettings.elm create mode 100644 modules/webapp/src/main/elm/Data/PeriodicQuerySettings.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/ChannelForm.elm rename modules/webapp/src/main/elm/Messages/Comp/{NotificationForm.elm => DueItemsTaskForm.elm} (85%) rename modules/webapp/src/main/elm/Messages/Comp/{NotificationTable.elm => DueItemsTaskList.elm} (93%) rename modules/webapp/src/main/elm/Messages/Comp/{NotificationManage.elm => DueItemsTaskManage.elm} (63%) create mode 100644 modules/webapp/src/main/elm/Messages/Comp/EventSample.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/NotificationHookForm.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/NotificationHookManage.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/NotificationHookTable.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/NotificationHttpForm.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/NotificationMailForm.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/NotificationMatrixForm.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskForm.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskList.elm create mode 100644 modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskManage.elm create mode 100644 modules/webapp/src/main/elm/Messages/Data/ChannelType.elm create mode 100644 modules/webapp/src/main/elm/Messages/Data/EventType.elm create mode 100644 website/site/content/docs/jsonminiquery/_index.md create mode 100644 website/site/content/docs/webapp/notification-01.png create mode 100644 website/site/content/docs/webapp/notification-02.png create mode 100644 website/site/content/docs/webapp/notification-03.png create mode 100644 website/site/content/docs/webapp/notification-04.png create mode 100644 website/site/content/docs/webapp/notification-05.png create mode 100644 website/site/content/docs/webapp/notification.md delete mode 100644 website/site/content/docs/webapp/notify-due-items.jpg delete mode 100644 website/site/content/docs/webapp/notify-due-items.png diff --git a/.redocly.lint-ignore.yaml b/.redocly.lint-ignore.yaml new file mode 100644 index 00000000..8b8c997a --- /dev/null +++ b/.redocly.lint-ignore.yaml @@ -0,0 +1,5 @@ +# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API. +# See https://redoc.ly/docs/cli/ for more information. +modules/restapi/src/main/resources/docspell-openapi.yml: + spec: + - '#/extraSchemas' diff --git a/build.sbt b/build.sbt index 6ac36289..522b24ee 100644 --- a/build.sbt +++ b/build.sbt @@ -20,7 +20,7 @@ val scalafixSettings = Seq( val sharedSettings = Seq( organization := "com.github.eikek", - scalaVersion := "2.13.6", + scalaVersion := "2.13.7", organizationName := "Eike K. & Contributors", licenses += ("AGPL-3.0-or-later", url( "https://spdx.org/licenses/AGPL-3.0-or-later.html" @@ -41,7 +41,8 @@ val sharedSettings = Seq( "-Wdead-code", "-Wunused", "-Wvalue-discard", - "-Wnumeric-widen" + "-Wnumeric-widen", + "-Ywarn-macros:after" ), javacOptions ++= Seq("-target", "1.8", "-source", "1.8"), LocalRootProject / toolsPackage := { @@ -272,6 +273,22 @@ val openapiScalaSettings = Seq( ) ) ) + case "channeltype" => + field => + field.copy(typeDef = + TypeDef("ChannelType", Imports("docspell.notification.api.ChannelType")) + ) + case "eventtype" => + field => + field.copy(typeDef = + TypeDef("EventType", Imports("docspell.notification.api.EventType")) + ) + + case "jsonminiq" => + field => + field.copy(typeDef = + TypeDef("JsonMiniQuery", Imports("docspell.jsonminiq.JsonMiniQuery")) + ) }) ) @@ -385,6 +402,34 @@ val totp = project Dependencies.circe ) +val jsonminiq = project + .in(file("modules/jsonminiq")) + .disablePlugins(RevolverPlugin) + .settings(sharedSettings) + .settings(testSettingsMUnit) + .settings( + name := "docspell-jsonminiq", + libraryDependencies ++= + Dependencies.circeCore ++ + Dependencies.catsParse ++ + Dependencies.circe.map(_ % Test) + ) + +val notificationApi = project + .in(file("modules/notification/api")) + .disablePlugins(RevolverPlugin) + .settings(sharedSettings) + .settings(testSettingsMUnit) + .settings( + name := "docspell-notification-api", + addCompilerPlugin(Dependencies.kindProjectorPlugin), + libraryDependencies ++= + Dependencies.fs2 ++ + Dependencies.emilCommon ++ + Dependencies.circeGenericExtra + ) + .dependsOn(common) + val store = project .in(file("modules/store")) .disablePlugins(RevolverPlugin) @@ -408,7 +453,27 @@ val store = project libraryDependencies ++= Dependencies.testContainer.map(_ % Test) ) - .dependsOn(common, query.jvm, totp, files) + .dependsOn(common, query.jvm, totp, files, notificationApi, jsonminiq) + +val notificationImpl = project + .in(file("modules/notification/impl")) + .disablePlugins(RevolverPlugin) + .settings(sharedSettings) + .settings(testSettingsMUnit) + .settings( + name := "docspell-notification-impl", + addCompilerPlugin(Dependencies.kindProjectorPlugin), + libraryDependencies ++= + Dependencies.fs2 ++ + Dependencies.emil ++ + Dependencies.emilMarkdown ++ + Dependencies.http4sClient ++ + Dependencies.http4sCirce ++ + Dependencies.http4sDsl ++ + Dependencies.yamusca ++ + Dependencies.yamuscaCirce + ) + .dependsOn(notificationApi, store, jsonminiq) val pubsubApi = project .in(file("modules/pubsub/api")) @@ -522,13 +587,13 @@ val restapi = project .settings( name := "docspell-restapi", libraryDependencies ++= - Dependencies.circe, + Dependencies.circe ++ Dependencies.emil, openapiTargetLanguage := Language.Scala, openapiPackage := Pkg("docspell.restapi.model"), openapiSpec := (Compile / resourceDirectory).value / "docspell-openapi.yml", openapiStaticGen := OpenApiDocGenerator.Redoc ) - .dependsOn(common, query.jvm) + .dependsOn(common, query.jvm, notificationApi, jsonminiq) val joexapi = project .in(file("modules/joexapi")) @@ -564,7 +629,7 @@ val backend = project Dependencies.http4sClient ++ Dependencies.emil ) - .dependsOn(store, joexapi, ftsclient, totp, pubsubApi) + .dependsOn(store, notificationApi, joexapi, ftsclient, totp, pubsubApi) val oidc = project .in(file("modules/oidc")) @@ -656,7 +721,8 @@ val joex = project joexapi, restapi, ftssolr, - pubsubNaive + pubsubNaive, + notificationImpl ) val restserver = project @@ -720,7 +786,17 @@ val restserver = project } } ) - .dependsOn(config, restapi, joexapi, backend, webapp, ftssolr, oidc, pubsubNaive) + .dependsOn( + config, + restapi, + joexapi, + backend, + webapp, + ftssolr, + oidc, + pubsubNaive, + notificationImpl + ) // --- Website Documentation @@ -811,10 +887,13 @@ val root = project restserver, query.jvm, query.js, + jsonminiq, totp, oidc, pubsubApi, - pubsubNaive + pubsubNaive, + notificationApi, + notificationImpl ) // --- Helpers diff --git a/modules/backend/src/main/scala/docspell/backend/AttachedEvent.scala b/modules/backend/src/main/scala/docspell/backend/AttachedEvent.scala new file mode 100644 index 00000000..015e771b --- /dev/null +++ b/modules/backend/src/main/scala/docspell/backend/AttachedEvent.scala @@ -0,0 +1,44 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.backend + +import docspell.common._ +import docspell.notification.api.Event + +trait AttachedEvent[R] { + + def value: R + + def event(account: AccountId, baseUrl: Option[LenientUri]): Iterable[Event] + + def map[U](f: R => U): AttachedEvent[U] +} + +object AttachedEvent { + + def only[R](v: R): AttachedEvent[R] = + new AttachedEvent[R] { + val value = v + def event(account: AccountId, baseUrl: Option[LenientUri]): Iterable[Event] = + Iterable.empty[Event] + + def map[U](f: R => U): AttachedEvent[U] = + only(f(v)) + } + + def apply[R]( + v: R + )(mkEvent: (AccountId, Option[LenientUri]) => Event): AttachedEvent[R] = + new AttachedEvent[R] { + val value = v + def event(account: AccountId, baseUrl: Option[LenientUri]): Iterable[Event] = + Some(mkEvent(account, baseUrl)) + + def map[U](f: R => U): AttachedEvent[U] = + apply(f(v))(mkEvent) + } +} diff --git a/modules/backend/src/main/scala/docspell/backend/BackendApp.scala b/modules/backend/src/main/scala/docspell/backend/BackendApp.scala index 9444901a..7bcaec3d 100644 --- a/modules/backend/src/main/scala/docspell/backend/BackendApp.scala +++ b/modules/backend/src/main/scala/docspell/backend/BackendApp.scala @@ -14,12 +14,13 @@ import docspell.backend.msg.JobQueuePublish import docspell.backend.ops._ import docspell.backend.signup.OSignup import docspell.ftsclient.FtsClient +import docspell.notification.api.{EventExchange, NotificationModule} import docspell.pubsub.api.PubSubT import docspell.store.Store import docspell.store.usertask.UserTaskStore import docspell.totp.Totp -import emil.javamail.{JavaMailEmil, Settings} +import emil.Emil trait BackendApp[F[_]] { @@ -46,19 +47,22 @@ trait BackendApp[F[_]] { def totp: OTotp[F] def share: OShare[F] def pubSub: PubSubT[F] + def events: EventExchange[F] + def notification: ONotification[F] } object BackendApp { def create[F[_]: Async]( - cfg: Config, store: Store[F], + javaEmil: Emil[F], ftsClient: FtsClient[F], - pubSubT: PubSubT[F] + pubSubT: PubSubT[F], + notificationMod: NotificationModule[F] ): Resource[F, BackendApp[F]] = for { utStore <- UserTaskStore(store) - queue <- JobQueuePublish(store, pubSubT) + queue <- JobQueuePublish(store, pubSubT, notificationMod) totpImpl <- OTotp(store, Totp.default) loginImpl <- Login[F](store, Totp.default) signupImpl <- OSignup[F](store) @@ -75,8 +79,6 @@ object BackendApp { itemImpl <- OItem(store, ftsClient, createIndex, queue, joexImpl) itemSearchImpl <- OItemSearch(store) fulltextImpl <- OFulltext(itemSearchImpl, ftsClient, store, queue, joexImpl) - javaEmil = - JavaMailEmil(Settings.defaultSettings.copy(debug = cfg.mailDebug)) mailImpl <- OMail(store, javaEmil) userTaskImpl <- OUserTask(utStore, queue, joexImpl) folderImpl <- OFolder(store) @@ -86,6 +88,7 @@ object BackendApp { shareImpl <- Resource.pure( OShare(store, itemSearchImpl, simpleSearchImpl, javaEmil) ) + notifyImpl <- ONotification(store, notificationMod) } yield new BackendApp[F] { val pubSub = pubSubT val login = loginImpl @@ -110,5 +113,7 @@ object BackendApp { val clientSettings = clientSettingsImpl val totp = totpImpl val share = shareImpl + val events = notificationMod + val notification = notifyImpl } } diff --git a/modules/backend/src/main/scala/docspell/backend/Config.scala b/modules/backend/src/main/scala/docspell/backend/Config.scala index 32fbce16..8ddce838 100644 --- a/modules/backend/src/main/scala/docspell/backend/Config.scala +++ b/modules/backend/src/main/scala/docspell/backend/Config.scala @@ -10,12 +10,18 @@ import docspell.backend.signup.{Config => SignupConfig} import docspell.common._ import docspell.store.JdbcConfig +import emil.javamail.Settings + case class Config( mailDebug: Boolean, jdbc: JdbcConfig, signup: SignupConfig, files: Config.Files -) {} +) { + + def mailSettings: Settings = + Settings.defaultSettings.copy(debug = mailDebug) +} object Config { diff --git a/modules/backend/src/main/scala/docspell/backend/JobFactory.scala b/modules/backend/src/main/scala/docspell/backend/JobFactory.scala index 4f4c4fc5..128dc097 100644 --- a/modules/backend/src/main/scala/docspell/backend/JobFactory.scala +++ b/modules/backend/src/main/scala/docspell/backend/JobFactory.scala @@ -9,10 +9,29 @@ package docspell.backend import cats.effect._ import cats.implicits._ +import docspell.backend.MailAddressCodec import docspell.common._ +import docspell.notification.api.ChannelOrRef._ +import docspell.notification.api.PeriodicQueryArgs import docspell.store.records.RJob -object JobFactory { +object JobFactory extends MailAddressCodec { + def periodicQuery[F[_]: Sync](args: PeriodicQueryArgs, submitter: AccountId): F[RJob] = + for { + id <- Ident.randomId[F] + now <- Timestamp.current[F] + job = RJob.newJob( + id, + PeriodicQueryArgs.taskName, + submitter.collective, + args, + s"Running periodic query, notify via ${args.channel.channelType}", + now, + submitter.user, + Priority.Low, + None + ) + } yield job def makePageCount[F[_]: Sync]( args: MakePageCountArgs, diff --git a/modules/backend/src/main/scala/docspell/backend/MailAddressCodec.scala b/modules/backend/src/main/scala/docspell/backend/MailAddressCodec.scala new file mode 100644 index 00000000..9c52c7cb --- /dev/null +++ b/modules/backend/src/main/scala/docspell/backend/MailAddressCodec.scala @@ -0,0 +1,22 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.backend + +import emil._ +import emil.javamail.syntax._ +import io.circe.{Decoder, Encoder} + +trait MailAddressCodec { + + implicit val jsonEncoder: Encoder[MailAddress] = + Encoder.encodeString.contramap(_.asUnicodeString) + + implicit val jsonDecoder: Decoder[MailAddress] = + Decoder.decodeString.emap(MailAddress.parse) +} + +object MailAddressCodec extends MailAddressCodec diff --git a/modules/backend/src/main/scala/docspell/backend/auth/Login.scala b/modules/backend/src/main/scala/docspell/backend/auth/Login.scala index 09e71ebd..12752962 100644 --- a/modules/backend/src/main/scala/docspell/backend/auth/Login.scala +++ b/modules/backend/src/main/scala/docspell/backend/auth/Login.scala @@ -275,8 +275,8 @@ object Login { token <- RememberToken.user(rme.id, config.serverSecret) } yield token - private def check(given: String)(data: QLogin.Data): Boolean = { - val passOk = BCrypt.checkpw(given, data.password.pass) + private def check(givenPass: String)(data: QLogin.Data): Boolean = { + val passOk = BCrypt.checkpw(givenPass, data.password.pass) checkNoPassword(data, Set(AccountSource.Local)) && passOk } diff --git a/modules/backend/src/main/scala/docspell/backend/msg/JobQueuePublish.scala b/modules/backend/src/main/scala/docspell/backend/msg/JobQueuePublish.scala index 64b0b6d6..d4011943 100644 --- a/modules/backend/src/main/scala/docspell/backend/msg/JobQueuePublish.scala +++ b/modules/backend/src/main/scala/docspell/backend/msg/JobQueuePublish.scala @@ -10,19 +10,36 @@ import cats.effect._ import cats.implicits._ import docspell.common.{Duration, Ident, Priority} +import docspell.notification.api.Event +import docspell.notification.api.EventSink import docspell.pubsub.api.PubSubT import docspell.store.Store import docspell.store.queue.JobQueue import docspell.store.records.RJob -final class JobQueuePublish[F[_]: Sync](delegate: JobQueue[F], pubsub: PubSubT[F]) - extends JobQueue[F] { +final class JobQueuePublish[F[_]: Sync]( + delegate: JobQueue[F], + pubsub: PubSubT[F], + eventSink: EventSink[F] +) extends JobQueue[F] { private def msg(job: RJob): JobSubmitted = JobSubmitted(job.id, job.group, job.task, job.args) + private def event(job: RJob): Event.JobSubmitted = + Event.JobSubmitted( + job.id, + job.group, + job.task, + job.args, + job.state, + job.subject, + job.submitter + ) + private def publish(job: RJob): F[Unit] = - pubsub.publish1(JobSubmitted.topic, msg(job)).as(()) + pubsub.publish1(JobSubmitted.topic, msg(job)).as(()) *> + eventSink.offer(event(job)) def insert(job: RJob) = delegate.insert(job).flatTap(_ => publish(job)) @@ -54,6 +71,10 @@ final class JobQueuePublish[F[_]: Sync](delegate: JobQueue[F], pubsub: PubSubT[F } object JobQueuePublish { - def apply[F[_]: Async](store: Store[F], pubSub: PubSubT[F]): Resource[F, JobQueue[F]] = - JobQueue(store).map(q => new JobQueuePublish[F](q, pubSub)) + def apply[F[_]: Async]( + store: Store[F], + pubSub: PubSubT[F], + eventSink: EventSink[F] + ): Resource[F, JobQueue[F]] = + JobQueue(store).map(q => new JobQueuePublish[F](q, pubSub, eventSink)) } diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OCustomFields.scala b/modules/backend/src/main/scala/docspell/backend/ops/OCustomFields.scala index 36d89fa0..258930a9 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OCustomFields.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OCustomFields.scala @@ -12,6 +12,7 @@ import cats.data.{NonEmptyList => Nel} import cats.effect._ import cats.implicits._ +import docspell.backend.AttachedEvent import docspell.backend.ops.OCustomFields.CustomFieldData import docspell.backend.ops.OCustomFields.CustomFieldOrder import docspell.backend.ops.OCustomFields.FieldValue @@ -20,6 +21,7 @@ import docspell.backend.ops.OCustomFields.RemoveValue import docspell.backend.ops.OCustomFields.SetValue import docspell.backend.ops.OCustomFields.SetValueResult import docspell.common._ +import docspell.notification.api.Event import docspell.store.AddResult import docspell.store.Store import docspell.store.UpdateResult @@ -53,12 +55,15 @@ trait OCustomFields[F[_]] { def delete(coll: Ident, fieldIdOrName: Ident): F[UpdateResult] /** Sets a value given a field an an item. Existing values are overwritten. */ - def setValue(item: Ident, value: SetValue): F[SetValueResult] + def setValue(item: Ident, value: SetValue): F[AttachedEvent[SetValueResult]] - def setValueMultiple(items: Nel[Ident], value: SetValue): F[SetValueResult] + def setValueMultiple( + items: Nel[Ident], + value: SetValue + ): F[AttachedEvent[SetValueResult]] /** Deletes a value for a given field an item. */ - def deleteValue(in: RemoveValue): F[UpdateResult] + def deleteValue(in: RemoveValue): F[AttachedEvent[UpdateResult]] /** Finds all values to the given items */ def findAllValues(itemIds: Nel[Ident]): F[List[FieldValue]] @@ -196,13 +201,13 @@ object OCustomFields { UpdateResult.fromUpdate(store.transact(update.getOrElse(0))) } - def setValue(item: Ident, value: SetValue): F[SetValueResult] = + def setValue(item: Ident, value: SetValue): F[AttachedEvent[SetValueResult]] = setValueMultiple(Nel.of(item), value) def setValueMultiple( items: Nel[Ident], value: SetValue - ): F[SetValueResult] = + ): F[AttachedEvent[SetValueResult]] = (for { field <- EitherT.fromOptionF( store.transact(RCustomField.findByIdOrName(value.field, value.collective)), @@ -224,17 +229,24 @@ object OCustomFields { .traverse(item => store.transact(RCustomField.setValue(field, item, fval))) .map(_.toList.sum) ) - } yield nu).fold(identity, _ => SetValueResult.success) + mkEvent = + Event.SetFieldValue.partial(items, field.id, fval) - def deleteValue(in: RemoveValue): F[UpdateResult] = { + } yield AttachedEvent(SetValueResult.success)(mkEvent)) + .fold(AttachedEvent.only, identity) + + def deleteValue(in: RemoveValue): F[AttachedEvent[UpdateResult]] = { val update = - for { + (for { field <- OptionT(RCustomField.findByIdOrName(in.field, in.collective)) _ <- OptionT.liftF(logger.debug(s"Field found by '${in.field}': $field")) n <- OptionT.liftF(RCustomFieldValue.deleteValue(field.id, in.item)) - } yield n + mkEvent = Event.DeleteFieldValue.partial(in.item, field.id) + } yield AttachedEvent(n)(mkEvent)) + .getOrElse(AttachedEvent.only(0)) + .map(_.map(UpdateResult.fromUpdateRows)) - UpdateResult.fromUpdate(store.transact(update.getOrElse(0))) + store.transact(update) } }) diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala index a45427fc..b49d09cc 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala @@ -6,15 +6,17 @@ package docspell.backend.ops -import cats.data.{NonEmptyList, OptionT} +import cats.data.{NonEmptyList => Nel, OptionT} import cats.effect.{Async, Resource} import cats.implicits._ +import docspell.backend.AttachedEvent import docspell.backend.JobFactory import docspell.backend.fulltext.CreateIndex import docspell.backend.item.Merge import docspell.common._ import docspell.ftsclient.FtsClient +import docspell.notification.api.Event import docspell.store.queries.{QAttachment, QItem, QMoveAttachment} import docspell.store.queue.JobQueue import docspell.store.records._ @@ -26,42 +28,54 @@ import org.log4s.getLogger trait OItem[F[_]] { /** Sets the given tags (removing all existing ones). */ - def setTags(item: Ident, tagIds: List[String], collective: Ident): F[UpdateResult] + def setTags( + item: Ident, + tagIds: List[String], + collective: Ident + ): F[AttachedEvent[UpdateResult]] /** Sets tags for multiple items. The tags of the items will be replaced with the given * ones. Same as `setTags` but for multiple items. */ def setTagsMultipleItems( - items: NonEmptyList[Ident], + items: Nel[Ident], tags: List[String], collective: Ident - ): F[UpdateResult] + ): F[AttachedEvent[UpdateResult]] /** Create a new tag and add it to the item. */ - def addNewTag(item: Ident, tag: RTag): F[AddResult] + def addNewTag(collective: Ident, item: Ident, tag: RTag): F[AttachedEvent[AddResult]] /** Apply all tags to the given item. Tags must exist, but can be IDs or names. Existing * tags on the item are left unchanged. */ - def linkTags(item: Ident, tags: List[String], collective: Ident): F[UpdateResult] + def linkTags( + item: Ident, + tags: List[String], + collective: Ident + ): F[AttachedEvent[UpdateResult]] def linkTagsMultipleItems( - items: NonEmptyList[Ident], + items: Nel[Ident], tags: List[String], collective: Ident - ): F[UpdateResult] + ): F[AttachedEvent[UpdateResult]] def removeTagsMultipleItems( - items: NonEmptyList[Ident], + items: Nel[Ident], tags: List[String], collective: Ident - ): F[UpdateResult] + ): F[AttachedEvent[UpdateResult]] /** Toggles tags of the given item. Tags must exist, but can be IDs or names. */ - def toggleTags(item: Ident, tags: List[String], collective: Ident): F[UpdateResult] + def toggleTags( + item: Ident, + tags: List[String], + collective: Ident + ): F[AttachedEvent[UpdateResult]] def setDirection( - item: NonEmptyList[Ident], + item: Nel[Ident], direction: Direction, collective: Ident ): F[UpdateResult] @@ -69,13 +83,13 @@ trait OItem[F[_]] { def setFolder(item: Ident, folder: Option[Ident], collective: Ident): F[UpdateResult] def setFolderMultiple( - items: NonEmptyList[Ident], + items: Nel[Ident], folder: Option[Ident], collective: Ident ): F[UpdateResult] def setCorrOrg( - items: NonEmptyList[Ident], + items: Nel[Ident], org: Option[Ident], collective: Ident ): F[UpdateResult] @@ -83,7 +97,7 @@ trait OItem[F[_]] { def addCorrOrg(item: Ident, org: OOrganization.OrgAndContacts): F[AddResult] def setCorrPerson( - items: NonEmptyList[Ident], + items: Nel[Ident], person: Option[Ident], collective: Ident ): F[UpdateResult] @@ -91,7 +105,7 @@ trait OItem[F[_]] { def addCorrPerson(item: Ident, person: OOrganization.PersonAndContacts): F[AddResult] def setConcPerson( - items: NonEmptyList[Ident], + items: Nel[Ident], person: Option[Ident], collective: Ident ): F[UpdateResult] @@ -99,7 +113,7 @@ trait OItem[F[_]] { def addConcPerson(item: Ident, person: OOrganization.PersonAndContacts): F[AddResult] def setConcEquip( - items: NonEmptyList[Ident], + items: Nel[Ident], equip: Option[Ident], collective: Ident ): F[UpdateResult] @@ -111,30 +125,30 @@ trait OItem[F[_]] { def setName(item: Ident, name: String, collective: Ident): F[UpdateResult] def setNameMultiple( - items: NonEmptyList[Ident], + items: Nel[Ident], name: String, collective: Ident ): F[UpdateResult] def setState(item: Ident, state: ItemState, collective: Ident): F[AddResult] = - setStates(NonEmptyList.of(item), state, collective) + setStates(Nel.of(item), state, collective) def setStates( - item: NonEmptyList[Ident], + item: Nel[Ident], state: ItemState, collective: Ident ): F[AddResult] - def restore(items: NonEmptyList[Ident], collective: Ident): F[UpdateResult] + def restore(items: Nel[Ident], collective: Ident): F[UpdateResult] def setItemDate( - item: NonEmptyList[Ident], + item: Nel[Ident], date: Option[Timestamp], collective: Ident ): F[UpdateResult] def setItemDueDate( - item: NonEmptyList[Ident], + item: Nel[Ident], date: Option[Timestamp], collective: Ident ): F[UpdateResult] @@ -143,14 +157,14 @@ trait OItem[F[_]] { def deleteItem(itemId: Ident, collective: Ident): F[Int] - def deleteItemMultiple(items: NonEmptyList[Ident], collective: Ident): F[Int] + def deleteItemMultiple(items: Nel[Ident], collective: Ident): F[Int] def deleteAttachment(id: Ident, collective: Ident): F[Int] - def setDeletedState(items: NonEmptyList[Ident], collective: Ident): F[Int] + def setDeletedState(items: Nel[Ident], collective: Ident): F[Int] def deleteAttachmentMultiple( - attachments: NonEmptyList[Ident], + attachments: Nel[Ident], collective: Ident ): F[Int] @@ -174,7 +188,7 @@ trait OItem[F[_]] { ): F[UpdateResult] def reprocessAll( - items: NonEmptyList[Ident], + items: Nel[Ident], account: AccountId, notifyJoex: Boolean ): F[UpdateResult] @@ -204,13 +218,12 @@ trait OItem[F[_]] { /** Merges a list of items into one item. The remaining items are deleted. */ def merge( logger: Logger[F], - items: NonEmptyList[Ident], + items: Nel[Ident], collective: Ident ): F[UpdateResult] } object OItem { - def apply[F[_]: Async]( store: Store[F], fts: FtsClient[F], @@ -227,7 +240,7 @@ object OItem { def merge( logger: Logger[F], - items: NonEmptyList[Ident], + items: Nel[Ident], collective: Ident ): F[UpdateResult] = Merge(logger, store, this, createIndex).merge(items, collective).attempt.map { @@ -250,52 +263,62 @@ object OItem { item: Ident, tags: List[String], collective: Ident - ): F[UpdateResult] = - linkTagsMultipleItems(NonEmptyList.of(item), tags, collective) + ): F[AttachedEvent[UpdateResult]] = + linkTagsMultipleItems(Nel.of(item), tags, collective) def linkTagsMultipleItems( - items: NonEmptyList[Ident], + items: Nel[Ident], tags: List[String], collective: Ident - ): F[UpdateResult] = + ): F[AttachedEvent[UpdateResult]] = tags.distinct match { - case Nil => UpdateResult.success.pure[F] + case Nil => AttachedEvent.only(UpdateResult.success).pure[F] case ws => - store.transact { - (for { - itemIds <- OptionT - .liftF(RItem.filterItems(items, collective)) - .filter(_.nonEmpty) - given <- OptionT.liftF(RTag.findAllByNameOrId(ws, collective)) - _ <- OptionT.liftF( - itemIds.traverse(item => - RTagItem.appendTags(item, given.map(_.tagId).toList) + store + .transact { + (for { + itemIds <- OptionT + .liftF(RItem.filterItems(items, collective)) + .subflatMap(l => Nel.fromFoldable(l)) + given <- OptionT.liftF(RTag.findAllByNameOrId(ws, collective)) + added <- OptionT.liftF( + itemIds.traverse(item => + RTagItem.appendTags(item, given.map(_.tagId).toList) + ) ) - ) - } yield UpdateResult.success).getOrElse(UpdateResult.notFound) - } + ev = Event.TagsChanged.partial( + itemIds, + added.toList.flatten.map(_.id).toList, + Nil + ) + } yield AttachedEvent(UpdateResult.success)(ev)) + .getOrElse(AttachedEvent.only(UpdateResult.notFound)) + } } def removeTagsMultipleItems( - items: NonEmptyList[Ident], + items: Nel[Ident], tags: List[String], collective: Ident - ): F[UpdateResult] = + ): F[AttachedEvent[UpdateResult]] = tags.distinct match { - case Nil => UpdateResult.success.pure[F] + case Nil => AttachedEvent.only(UpdateResult.success).pure[F] case ws => store.transact { (for { itemIds <- OptionT .liftF(RItem.filterItems(items, collective)) - .filter(_.nonEmpty) + .subflatMap(l => Nel.fromFoldable(l)) given <- OptionT.liftF(RTag.findAllByNameOrId(ws, collective)) _ <- OptionT.liftF( itemIds.traverse(item => RTagItem.removeAllTags(item, given.map(_.tagId).toList) ) ) - } yield UpdateResult.success).getOrElse(UpdateResult.notFound) + mkEvent = Event.TagsChanged + .partial(itemIds, Nil, given.map(_.tagId.id).toList) + } yield AttachedEvent(UpdateResult.success)(mkEvent)) + .getOrElse(AttachedEvent.only(UpdateResult.notFound)) } } @@ -303,9 +326,9 @@ object OItem { item: Ident, tags: List[String], collective: Ident - ): F[UpdateResult] = + ): F[AttachedEvent[UpdateResult]] = tags.distinct match { - case Nil => UpdateResult.success.pure[F] + case Nil => AttachedEvent.only(UpdateResult.success).pure[F] case kws => val db = (for { @@ -316,7 +339,14 @@ object OItem { toadd = given.map(_.tagId).diff(exist.map(_.tagId)) _ <- OptionT.liftF(RTagItem.setAllTags(item, toadd)) _ <- OptionT.liftF(RTagItem.removeAllTags(item, remove.toSeq)) - } yield UpdateResult.success).getOrElse(UpdateResult.notFound) + mkEvent = Event.TagsChanged.partial( + Nel.of(item), + toadd.map(_.id).toList, + remove.map(_.id).toList + ) + + } yield AttachedEvent(UpdateResult.success)(mkEvent)) + .getOrElse(AttachedEvent.only(UpdateResult.notFound)) store.transact(db) } @@ -325,41 +355,69 @@ object OItem { item: Ident, tagIds: List[String], collective: Ident - ): F[UpdateResult] = - setTagsMultipleItems(NonEmptyList.of(item), tagIds, collective) + ): F[AttachedEvent[UpdateResult]] = + setTagsMultipleItems(Nel.of(item), tagIds, collective) def setTagsMultipleItems( - items: NonEmptyList[Ident], + items: Nel[Ident], tags: List[String], collective: Ident - ): F[UpdateResult] = - UpdateResult.fromUpdate(store.transact(for { - k <- RTagItem.deleteItemTags(items, collective) - rtags <- RTag.findAllByNameOrId(tags, collective) - res <- items.traverse(i => RTagItem.setAllTags(i, rtags.map(_.tagId))) - n = res.fold - } yield k + n)) + ): F[AttachedEvent[UpdateResult]] = { + val dbTask = + for { + k <- RTagItem.deleteItemTags(items, collective) + given <- RTag.findAllByNameOrId(tags, collective) + res <- items.traverse(i => RTagItem.setAllTags(i, given.map(_.tagId))) + n = res.fold + mkEvent = Event.TagsChanged.partial( + items, + given.map(_.tagId.id).toList, + Nil + ) + } yield AttachedEvent(k + n)(mkEvent) - def addNewTag(item: Ident, tag: RTag): F[AddResult] = + for { + data <- store.transact(dbTask) + } yield data.map(UpdateResult.fromUpdateRows) + } + + def addNewTag( + collective: Ident, + item: Ident, + tag: RTag + ): F[AttachedEvent[AddResult]] = (for { _ <- OptionT(store.transact(RItem.getCollective(item))) .filter(_ == tag.collective) addres <- OptionT.liftF(otag.add(tag)) - _ <- addres match { + res <- addres match { case AddResult.Success => OptionT.liftF( - store.transact(RTagItem.setAllTags(item, List(tag.tagId))) + store + .transact(RTagItem.setAllTags(item, List(tag.tagId))) + .map { _ => + AttachedEvent(())( + Event.TagsChanged.partial( + Nel.of(item), + List(tag.tagId.id), + Nil + ) + ) + } ) + case AddResult.EntityExists(_) => - OptionT.pure[F](0) + OptionT.pure[F](AttachedEvent.only(())) case AddResult.Failure(_) => - OptionT.pure[F](0) + OptionT.pure[F](AttachedEvent.only(())) } - } yield addres) - .getOrElse(AddResult.Failure(new Exception("Collective mismatch"))) + } yield res.map(_ => addres)) + .getOrElse( + AttachedEvent.only(AddResult.Failure(new Exception("Collective mismatch"))) + ) def setDirection( - items: NonEmptyList[Ident], + items: Nel[Ident], direction: Direction, collective: Ident ): F[UpdateResult] = @@ -383,7 +441,7 @@ object OItem { ) def setFolderMultiple( - items: NonEmptyList[Ident], + items: Nel[Ident], folder: Option[Ident], collective: Ident ): F[UpdateResult] = @@ -404,7 +462,7 @@ object OItem { } yield res def setCorrOrg( - items: NonEmptyList[Ident], + items: Nel[Ident], org: Option[Ident], collective: Ident ): F[UpdateResult] = @@ -423,7 +481,7 @@ object OItem { OptionT.liftF( store.transact( RItem.updateCorrOrg( - NonEmptyList.of(item), + Nel.of(item), org.org.cid, Some(org.org.oid) ) @@ -438,7 +496,7 @@ object OItem { .getOrElse(AddResult.Failure(new Exception("Collective mismatch"))) def setCorrPerson( - items: NonEmptyList[Ident], + items: Nel[Ident], person: Option[Ident], collective: Ident ): F[UpdateResult] = @@ -461,7 +519,7 @@ object OItem { store.transact( RItem .updateCorrPerson( - NonEmptyList.of(item), + Nel.of(item), person.person.cid, Some(person.person.pid) ) @@ -476,7 +534,7 @@ object OItem { .getOrElse(AddResult.Failure(new Exception("Collective mismatch"))) def setConcPerson( - items: NonEmptyList[Ident], + items: Nel[Ident], person: Option[Ident], collective: Ident ): F[UpdateResult] = @@ -499,7 +557,7 @@ object OItem { store.transact( RItem .updateConcPerson( - NonEmptyList.of(item), + Nel.of(item), person.person.cid, Some(person.person.pid) ) @@ -514,7 +572,7 @@ object OItem { .getOrElse(AddResult.Failure(new Exception("Collective mismatch"))) def setConcEquip( - items: NonEmptyList[Ident], + items: Nel[Ident], equip: Option[Ident], collective: Ident ): F[UpdateResult] = @@ -533,7 +591,7 @@ object OItem { OptionT.liftF( store.transact( RItem - .updateConcEquip(NonEmptyList.of(item), equip.cid, Some(equip.eid)) + .updateConcEquip(Nel.of(item), equip.cid, Some(equip.eid)) ) ) case AddResult.EntityExists(_) => @@ -569,7 +627,7 @@ object OItem { ) def setNameMultiple( - items: NonEmptyList[Ident], + items: Nel[Ident], name: String, collective: Ident ): F[UpdateResult] = @@ -590,7 +648,7 @@ object OItem { } yield res def setStates( - items: NonEmptyList[Ident], + items: Nel[Ident], state: ItemState, collective: Ident ): F[AddResult] = @@ -600,7 +658,7 @@ object OItem { .map(AddResult.fromUpdate) def restore( - items: NonEmptyList[Ident], + items: Nel[Ident], collective: Ident ): F[UpdateResult] = UpdateResult.fromUpdate(for { @@ -612,7 +670,7 @@ object OItem { } yield n) def setItemDate( - items: NonEmptyList[Ident], + items: Nel[Ident], date: Option[Timestamp], collective: Ident ): F[UpdateResult] = @@ -622,7 +680,7 @@ object OItem { ) def setItemDueDate( - items: NonEmptyList[Ident], + items: Nel[Ident], date: Option[Timestamp], collective: Ident ): F[UpdateResult] = @@ -636,14 +694,14 @@ object OItem { .delete(store)(itemId, collective) .flatTap(_ => fts.removeItem(logger, itemId)) - def deleteItemMultiple(items: NonEmptyList[Ident], collective: Ident): F[Int] = + def deleteItemMultiple(items: Nel[Ident], collective: Ident): F[Int] = for { itemIds <- store.transact(RItem.filterItems(items, collective)) results <- itemIds.traverse(item => deleteItem(item, collective)) n = results.sum } yield n - def setDeletedState(items: NonEmptyList[Ident], collective: Ident): F[Int] = + def setDeletedState(items: Nel[Ident], collective: Ident): F[Int] = for { n <- store.transact(RItem.setState(items, collective, ItemState.Deleted)) _ <- items.traverse(id => fts.removeItem(logger, id)) @@ -658,7 +716,7 @@ object OItem { .flatTap(_ => fts.removeAttachment(logger, id)) def deleteAttachmentMultiple( - attachments: NonEmptyList[Ident], + attachments: Nel[Ident], collective: Ident ): F[Int] = for { @@ -710,7 +768,7 @@ object OItem { } yield UpdateResult.success).getOrElse(UpdateResult.notFound) def reprocessAll( - items: NonEmptyList[Ident], + items: Nel[Ident], account: AccountId, notifyJoex: Boolean ): F[UpdateResult] = diff --git a/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala new file mode 100644 index 00000000..992955fa --- /dev/null +++ b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala @@ -0,0 +1,347 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.backend.ops + +import java.io.PrintWriter +import java.io.StringWriter + +import cats.data.OptionT +import cats.data.{NonEmptyList => Nel} +import cats.effect._ +import cats.implicits._ + +import docspell.backend.ops.ONotification.Hook +import docspell.common._ +import docspell.jsonminiq.JsonMiniQuery +import docspell.notification.api._ +import docspell.store.AddResult +import docspell.store.Store +import docspell.store.UpdateResult +import docspell.store.queries.QNotification +import docspell.store.records._ + +trait ONotification[F[_]] { + + def sendMessage( + logger: Logger[F], + data: EventContext, + channels: Seq[NotificationChannel] + ): F[Unit] + + def offerEvents(ev: Iterable[Event]): F[Unit] + + def mkNotificationChannel(channel: Channel): F[Vector[NotificationChannel]] + + def findNotificationChannel(ref: ChannelRef): F[Vector[NotificationChannel]] + + def listChannels(account: AccountId): F[Vector[Channel]] + + def deleteChannel(id: Ident, account: AccountId): F[UpdateResult] + + def createChannel(channel: Channel, account: AccountId): F[AddResult] + + def updateChannel(channel: Channel, account: AccountId): F[UpdateResult] + + def listHooks(account: AccountId): F[Vector[Hook]] + + def deleteHook(id: Ident, account: AccountId): F[UpdateResult] + + def createHook(hook: Hook, account: AccountId): F[AddResult] + + def updateHook(hook: Hook, account: AccountId): F[UpdateResult] + + def sampleEvent( + evt: EventType, + account: AccountId, + baseUrl: Option[LenientUri] + ): F[EventContext] + + def sendSampleEvent( + evt: EventType, + channel: Channel, + account: AccountId, + baseUrl: Option[LenientUri] + ): F[ONotification.SendTestResult] +} + +object ONotification { + private[this] val logger = org.log4s.getLogger + + def apply[F[_]: Async]( + store: Store[F], + notMod: NotificationModule[F] + ): Resource[F, ONotification[F]] = + Resource.pure[F, ONotification[F]](new ONotification[F] { + val log = Logger.log4s[F](logger) + + def withUserId[A]( + account: AccountId + )(f: Ident => F[UpdateResult]): F[UpdateResult] = + OptionT(store.transact(RUser.findIdByAccount(account))) + .semiflatMap(f) + .getOrElse(UpdateResult.notFound) + + def offerEvents(ev: Iterable[Event]): F[Unit] = + ev.toList.traverse(notMod.offer(_)).as(()) + + def sendMessage( + logger: Logger[F], + data: EventContext, + channels: Seq[NotificationChannel] + ): F[Unit] = + notMod.send(logger, data, channels) + + def sampleEvent( + evt: EventType, + account: AccountId, + baseUrl: Option[LenientUri] + ): F[EventContext] = + Event + .sample[F](evt, account, baseUrl) + .flatMap(notMod.sampleEvent.run) + + def sendSampleEvent( + evt: EventType, + channel: Channel, + account: AccountId, + baseUrl: Option[LenientUri] + ): F[SendTestResult] = + (for { + ev <- sampleEvent(evt, account, baseUrl) + logbuf <- Logger.buffer() + ch <- mkNotificationChannel(channel) + _ <- notMod.send(logbuf._2.andThen(log), ev, ch) + logs <- logbuf._1.get + res = SendTestResult(true, logs) + } yield res).attempt + .map { + case Right(res) => res + case Left(ex) => + val ps = new StringWriter() + ex.printStackTrace(new PrintWriter(ps)) + SendTestResult(false, Vector(s"${ex.getMessage}\n$ps")) + } + + def listChannels(account: AccountId): F[Vector[Channel]] = + store + .transact(RNotificationChannel.getByAccount(account)) + .map(_.map(ChannelConv.makeChannel)) + + def deleteChannel(id: Ident, account: AccountId): F[UpdateResult] = + UpdateResult + .fromUpdate( + store.transact(RNotificationChannel.deleteByAccount(id, account)) + ) + .flatTap(_ => log.info(s"Deleted channel ${id.id} for ${account.asString}")) + + def createChannel(channel: Channel, account: AccountId): F[AddResult] = + (for { + newId <- OptionT.liftF(Ident.randomId[F]) + userId <- OptionT(store.transact(RUser.findIdByAccount(account))) + r <- ChannelConv.makeRecord[F](store, Right(channel), newId, userId) + _ <- OptionT.liftF(store.transact(RNotificationChannel.insert(r))) + _ <- OptionT.liftF(log.debug(s"Created channel $r for $account")) + } yield AddResult.Success) + .getOrElse(AddResult.failure(new Exception("User not found!"))) + + def updateChannel(channel: Channel, account: AccountId): F[UpdateResult] = + (for { + userId <- OptionT(store.transact(RUser.findIdByAccount(account))) + r <- ChannelConv.makeRecord[F](store, Right(channel), channel.id, userId) + n <- OptionT.liftF(store.transact(RNotificationChannel.update(r))) + } yield UpdateResult.fromUpdateRows(n)).getOrElse(UpdateResult.notFound) + + def listHooks(account: AccountId): F[Vector[Hook]] = + store.transact(for { + list <- RNotificationHook.findAllByAccount(account) + res <- list.traverse((Hook.fromRecord _).tupled) + } yield res) + + def deleteHook(id: Ident, account: AccountId): F[UpdateResult] = + UpdateResult + .fromUpdate(store.transact(RNotificationHook.deleteByAccount(id, account))) + + def createHook(hook: Hook, account: AccountId): F[AddResult] = + (for { + _ <- OptionT.liftF(log.debug(s"Creating new notification hook: $hook")) + channelId <- OptionT.liftF(Ident.randomId[F]) + userId <- OptionT(store.transact(RUser.findIdByAccount(account))) + r <- ChannelConv.makeRecord[F](store, hook.channel, channelId, userId) + _ <- OptionT.liftF( + if (channelId == r.id) store.transact(RNotificationChannel.insert(r)) + else ().pure[F] + ) + _ <- OptionT.liftF(log.debug(s"Created channel $r for $account")) + hr <- OptionT.liftF(Hook.makeRecord(r, userId, hook)) + _ <- OptionT.liftF(store.transact(RNotificationHook.insert(hr))) + _ <- OptionT.liftF( + store.transact(RNotificationHookEvent.insertAll(hr.id, hook.events)) + ) + } yield AddResult.Success) + .getOrElse(AddResult.failure(new Exception("User or channel not found!"))) + + def updateHook(hook: Hook, account: AccountId): F[UpdateResult] = { + def withHook(f: RNotificationHook => F[UpdateResult]): F[UpdateResult] = + withUserId(account)(userId => + OptionT(store.transact(RNotificationHook.getById(hook.id, userId))) + .semiflatMap(f) + .getOrElse(UpdateResult.notFound) + ) + + def withChannel( + r: RNotificationHook + )(f: RNotificationChannel => F[UpdateResult]): F[UpdateResult] = + ChannelConv + .makeRecord(store, hook.channel, r.channelId, r.uid) + .semiflatMap(f) + .getOrElse(UpdateResult.notFound) + + def doUpdate(r: RNotificationHook): F[UpdateResult] = + withChannel(r) { ch => + UpdateResult.fromUpdate(store.transact(for { + nc <- RNotificationChannel.update(ch) + ne <- RNotificationHookEvent.updateAll( + r.id, + if (hook.allEvents) Nil else hook.events + ) + nr <- RNotificationHook.update( + r.copy( + enabled = hook.enabled, + allEvents = hook.allEvents, + eventFilter = hook.eventFilter + ) + ) + } yield nc + ne + nr)) + } + + withHook(doUpdate) + } + + def mkNotificationChannel(channel: Channel): F[Vector[NotificationChannel]] = + (for { + rec <- ChannelConv + .makeRecord(store, Right(channel), channel.id, Ident.unsafe("")) + ch <- OptionT.liftF(store.transact(QNotification.readChannel(rec))) + } yield ch).getOrElse(Vector.empty) + + def findNotificationChannel(ref: ChannelRef): F[Vector[NotificationChannel]] = + (for { + rec <- OptionT(store.transact(RNotificationChannel.getByRef(ref))) + ch <- OptionT.liftF(store.transact(QNotification.readChannel(rec))) + } yield ch).getOrElse(Vector.empty) + }) + + object ChannelConv { + + private[ops] def makeChannel(r: RNotificationChannel): Channel = + r.fold( + mail => + Channel.Mail(mail.id, mail.connection, Nel.fromListUnsafe(mail.recipients)), + gotify => Channel.Gotify(r.id, gotify.url, gotify.appKey), + matrix => + Channel.Matrix(r.id, matrix.homeServer, matrix.roomId, matrix.accessToken), + http => Channel.Http(r.id, http.url) + ) + + private[ops] def makeRecord[F[_]: Sync]( + store: Store[F], + channelIn: Either[ChannelRef, Channel], + id: Ident, + userId: Ident + ): OptionT[F, RNotificationChannel] = + channelIn match { + case Left(ref) => + OptionT(store.transact(RNotificationChannel.getByRef(ref))) + + case Right(channel) => + for { + time <- OptionT.liftF(Timestamp.current[F]) + r <- + channel match { + case Channel.Mail(_, conn, recipients) => + for { + mailConn <- OptionT( + store.transact(RUserEmail.getByUser(userId, conn)) + ) + rec = RNotificationChannelMail( + id, + userId, + mailConn.id, + recipients.toList, + time + ).vary + } yield rec + case Channel.Gotify(_, url, appKey) => + OptionT.pure[F]( + RNotificationChannelGotify(id, userId, url, appKey, time).vary + ) + case Channel.Matrix(_, homeServer, roomId, accessToken) => + OptionT.pure[F]( + RNotificationChannelMatrix( + id, + userId, + homeServer, + roomId, + accessToken, + "m.text", + time + ).vary + ) + case Channel.Http(_, url) => + OptionT.pure[F](RNotificationChannelHttp(id, userId, url, time).vary) + } + } yield r + } + } + + final case class Hook( + id: Ident, + enabled: Boolean, + channel: Either[ChannelRef, Channel], + allEvents: Boolean, + eventFilter: Option[JsonMiniQuery], + events: List[EventType] + ) + + object Hook { + import doobie._ + + private[ops] def fromRecord( + r: RNotificationHook, + events: List[EventType] + ): ConnectionIO[Hook] = + RNotificationChannel + .getByHook(r) + .map(_.head) + .map(ChannelConv.makeChannel) + .map(ch => Hook(r.id, r.enabled, Right(ch), r.allEvents, r.eventFilter, events)) + + private[ops] def makeRecord[F[_]: Sync]( + ch: RNotificationChannel, + userId: Ident, + hook: Hook + ): F[RNotificationHook] = + for { + id <- Ident.randomId[F] + time <- Timestamp.current[F] + h = RNotificationHook( + id, + userId, + hook.enabled, + ch.fold(_.id.some, _ => None, _ => None, _ => None), + ch.fold(_ => None, _.id.some, _ => None, _ => None), + ch.fold(_ => None, _ => None, _.id.some, _ => None), + ch.fold(_ => None, _ => None, _ => None, _.id.some), + hook.allEvents, + hook.eventFilter, + time + ) + } yield h + } + + final case class SendTestResult(success: Boolean, logMessages: Vector[String]) +} diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OUserTask.scala b/modules/backend/src/main/scala/docspell/backend/ops/OUserTask.scala index 2e44b0f5..dfc77491 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OUserTask.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OUserTask.scala @@ -11,7 +11,10 @@ import cats.effect._ import cats.implicits._ import fs2.Stream +import docspell.backend.MailAddressCodec._ import docspell.common._ +import docspell.notification.api.PeriodicDueItemsArgs +import docspell.notification.api.PeriodicQueryArgs import docspell.store.queue.JobQueue import docspell.store.usertask._ @@ -19,6 +22,22 @@ import io.circe.Encoder trait OUserTask[F[_]] { + /** Return the settings for all periodic-query tasks of the given user */ + def getPeriodicQuery(scope: UserTaskScope): Stream[F, UserTask[PeriodicQueryArgs]] + + /** Find a periodic-query task by the given id. */ + def findPeriodicQuery( + id: Ident, + scope: UserTaskScope + ): OptionT[F, UserTask[PeriodicQueryArgs]] + + /** Updates the periodic-query task of the given user. */ + def submitPeriodicQuery( + scope: UserTaskScope, + subject: Option[String], + task: UserTask[PeriodicQueryArgs] + ): F[Unit] + /** Return the settings for all scan-mailbox tasks of the current user. */ def getScanMailbox(scope: UserTaskScope): Stream[F, UserTask[ScanMailboxArgs]] @@ -36,19 +55,19 @@ trait OUserTask[F[_]] { ): F[Unit] /** Return the settings for all the notify-due-items task of the current user. */ - def getNotifyDueItems(scope: UserTaskScope): Stream[F, UserTask[NotifyDueItemsArgs]] + def getNotifyDueItems(scope: UserTaskScope): Stream[F, UserTask[PeriodicDueItemsArgs]] /** Find a notify-due-items task by the given id. */ def findNotifyDueItems( id: Ident, scope: UserTaskScope - ): OptionT[F, UserTask[NotifyDueItemsArgs]] + ): OptionT[F, UserTask[PeriodicDueItemsArgs]] /** Updates the notify-due-items tasks and notifies the joex nodes. */ def submitNotifyDueItems( scope: UserTaskScope, subject: Option[String], - task: UserTask[NotifyDueItemsArgs] + task: UserTask[PeriodicDueItemsArgs] ): F[Unit] /** Removes a user task with the given id. */ @@ -109,23 +128,42 @@ object OUserTask { def getNotifyDueItems( scope: UserTaskScope - ): Stream[F, UserTask[NotifyDueItemsArgs]] = + ): Stream[F, UserTask[PeriodicDueItemsArgs]] = store - .getByName[NotifyDueItemsArgs](scope, NotifyDueItemsArgs.taskName) + .getByName[PeriodicDueItemsArgs](scope, PeriodicDueItemsArgs.taskName) def findNotifyDueItems( id: Ident, scope: UserTaskScope - ): OptionT[F, UserTask[NotifyDueItemsArgs]] = + ): OptionT[F, UserTask[PeriodicDueItemsArgs]] = OptionT(getNotifyDueItems(scope).find(_.id == id).compile.last) def submitNotifyDueItems( scope: UserTaskScope, subject: Option[String], - task: UserTask[NotifyDueItemsArgs] + task: UserTask[PeriodicDueItemsArgs] ): F[Unit] = for { - _ <- store.updateTask[NotifyDueItemsArgs](scope, subject, task) + _ <- store.updateTask[PeriodicDueItemsArgs](scope, subject, task) + _ <- joex.notifyAllNodes + } yield () + + def getPeriodicQuery(scope: UserTaskScope): Stream[F, UserTask[PeriodicQueryArgs]] = + store.getByName[PeriodicQueryArgs](scope, PeriodicQueryArgs.taskName) + + def findPeriodicQuery( + id: Ident, + scope: UserTaskScope + ): OptionT[F, UserTask[PeriodicQueryArgs]] = + OptionT(getPeriodicQuery(scope).find(_.id == id).compile.last) + + def submitPeriodicQuery( + scope: UserTaskScope, + subject: Option[String], + task: UserTask[PeriodicQueryArgs] + ): F[Unit] = + for { + _ <- store.updateTask[PeriodicQueryArgs](scope, subject, task) _ <- joex.notifyAllNodes } yield () }) diff --git a/modules/common/src/main/scala/docspell/common/ItemQueryString.scala b/modules/common/src/main/scala/docspell/common/ItemQueryString.scala index 26da4d39..e866fbc7 100644 --- a/modules/common/src/main/scala/docspell/common/ItemQueryString.scala +++ b/modules/common/src/main/scala/docspell/common/ItemQueryString.scala @@ -6,6 +6,8 @@ package docspell.common +import io.circe.{Decoder, Encoder} + final case class ItemQueryString(query: String) { def isEmpty: Boolean = query.isEmpty @@ -15,4 +17,9 @@ object ItemQueryString { def apply(qs: Option[String]): ItemQueryString = ItemQueryString(qs.getOrElse("")) + + implicit val jsonEncoder: Encoder[ItemQueryString] = + Encoder.encodeString.contramap(_.query) + implicit val jsonDecoder: Decoder[ItemQueryString] = + Decoder.decodeString.map(ItemQueryString.apply) } diff --git a/modules/common/src/main/scala/docspell/common/LenientUri.scala b/modules/common/src/main/scala/docspell/common/LenientUri.scala index f76f9b0d..4061969d 100644 --- a/modules/common/src/main/scala/docspell/common/LenientUri.scala +++ b/modules/common/src/main/scala/docspell/common/LenientUri.scala @@ -103,6 +103,8 @@ case class LenientUri( val fragPart = fragment.map(f => s"#$f").getOrElse("") s"$schemePart:$authPart$pathPart$queryPart$fragPart" } + override def toString(): String = + asString } object LenientUri { diff --git a/modules/common/src/main/scala/docspell/common/Logger.scala b/modules/common/src/main/scala/docspell/common/Logger.scala index 01265ef4..66b583e2 100644 --- a/modules/common/src/main/scala/docspell/common/Logger.scala +++ b/modules/common/src/main/scala/docspell/common/Logger.scala @@ -6,8 +6,11 @@ package docspell.common +import java.io.{PrintWriter, StringWriter} + import cats.Applicative -import cats.effect.Sync +import cats.effect.{Ref, Sync} +import cats.implicits._ import fs2.Stream import docspell.common.syntax.all._ @@ -42,6 +45,28 @@ trait Logger[F[_]] { self => def error(ex: Throwable)(msg: => String): Stream[F, Unit] = Stream.eval(self.error(ex)(msg)) } + def andThen(other: Logger[F])(implicit F: Sync[F]): Logger[F] = { + val self = this + new Logger[F] { + def trace(msg: => String) = + self.trace(msg) >> other.trace(msg) + + override def debug(msg: => String) = + self.debug(msg) >> other.debug(msg) + + override def info(msg: => String) = + self.info(msg) >> other.info(msg) + + override def warn(msg: => String) = + self.warn(msg) >> other.warn(msg) + + override def error(ex: Throwable)(msg: => String) = + self.error(ex)(msg) >> other.error(ex)(msg) + + override def error(msg: => String) = + self.error(msg) >> other.error(msg) + } + } } object Logger { @@ -88,4 +113,31 @@ object Logger { log.ferror(msg) } + def buffer[F[_]: Sync](): F[(Ref[F, Vector[String]], Logger[F])] = + for { + buffer <- Ref.of[F, Vector[String]](Vector.empty[String]) + logger = new Logger[F] { + def trace(msg: => String) = + buffer.update(_.appended(s"TRACE $msg")) + + def debug(msg: => String) = + buffer.update(_.appended(s"DEBUG $msg")) + + def info(msg: => String) = + buffer.update(_.appended(s"INFO $msg")) + + def warn(msg: => String) = + buffer.update(_.appended(s"WARN $msg")) + + def error(ex: Throwable)(msg: => String) = { + val ps = new StringWriter() + ex.printStackTrace(new PrintWriter(ps)) + buffer.update(_.appended(s"ERROR $msg:\n$ps")) + } + + def error(msg: => String) = + buffer.update(_.appended(s"ERROR $msg")) + } + } yield (buffer, logger) + } diff --git a/modules/common/src/main/scala/docspell/common/NotifyDueItemsArgs.scala b/modules/common/src/main/scala/docspell/common/NotifyDueItemsArgs.scala index 1b1da90b..ff3ff9b1 100644 --- a/modules/common/src/main/scala/docspell/common/NotifyDueItemsArgs.scala +++ b/modules/common/src/main/scala/docspell/common/NotifyDueItemsArgs.scala @@ -27,7 +27,7 @@ case class NotifyDueItemsArgs( daysBack: Option[Int], tagsInclude: List[Ident], tagsExclude: List[Ident] -) {} +) object NotifyDueItemsArgs { diff --git a/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala b/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala index 41dee0ab..3bc993f9 100644 --- a/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala +++ b/modules/joex/src/main/scala/docspell/joex/JoexAppImpl.scala @@ -11,6 +11,7 @@ import cats.implicits._ import fs2.concurrent.SignallingRef import docspell.analysis.TextAnalyser +import docspell.backend.MailAddressCodec import docspell.backend.fulltext.CreateIndex import docspell.backend.msg.{CancelJob, JobQueuePublish, Topics} import docspell.backend.ops._ @@ -32,6 +33,8 @@ import docspell.joex.process.ReProcessItem import docspell.joex.scanmailbox._ import docspell.joex.scheduler._ import docspell.joex.updatecheck._ +import docspell.notification.api.NotificationModule +import docspell.notification.impl.NotificationModuleImpl import docspell.pubsub.api.{PubSub, PubSubT} import docspell.store.Store import docspell.store.queue._ @@ -49,16 +52,19 @@ final class JoexAppImpl[F[_]: Async]( pubSubT: PubSubT[F], pstore: PeriodicTaskStore[F], termSignal: SignallingRef[F, Boolean], + notificationMod: NotificationModule[F], val scheduler: Scheduler[F], val periodicScheduler: PeriodicScheduler[F] ) extends JoexApp[F] { def init: F[Unit] = { val run = scheduler.start.compile.drain val prun = periodicScheduler.start.compile.drain + val eventConsume = notificationMod.consumeAllEvents(2).compile.drain for { _ <- scheduleBackgroundTasks _ <- Async[F].start(run) _ <- Async[F].start(prun) + _ <- Async[F].start(eventConsume) _ <- scheduler.periodicAwake _ <- periodicScheduler.periodicAwake _ <- subscriptions @@ -115,7 +121,7 @@ final class JoexAppImpl[F[_]: Async]( } -object JoexAppImpl { +object JoexAppImpl extends MailAddressCodec { def create[F[_]: Async]( cfg: Config, @@ -130,7 +136,12 @@ object JoexAppImpl { pubSub, Logger.log4s(org.log4s.getLogger(s"joex-${cfg.appId.id}")) ) - queue <- JobQueuePublish(store, pubSubT) + javaEmil = + JavaMailEmil(Settings.defaultSettings.copy(debug = cfg.mailDebug)) + notificationMod <- Resource.eval( + NotificationModuleImpl[F](store, javaEmil, httpClient, 200) + ) + queue <- JobQueuePublish(store, pubSubT, notificationMod) joex <- OJoex(pubSubT) upload <- OUpload(store, queue, joex) fts <- createFtsClient(cfg)(httpClient) @@ -140,11 +151,11 @@ object JoexAppImpl { analyser <- TextAnalyser.create[F](cfg.textAnalysis.textAnalysisConfig) regexNer <- RegexNerFile(cfg.textAnalysis.regexNerFileConfig, store) updateCheck <- UpdateCheck.resource(httpClient) - javaEmil = - JavaMailEmil(Settings.defaultSettings.copy(debug = cfg.mailDebug)) + notification <- ONotification(store, notificationMod) sch <- SchedulerBuilder(cfg.scheduler, store) .withQueue(queue) .withPubSub(pubSubT) + .withEventSink(notificationMod) .withTask( JobTask.json( ProcessItemArgs.taskName, @@ -263,6 +274,20 @@ object JoexAppImpl { UpdateCheckTask.onCancel[F] ) ) + .withTask( + JobTask.json( + PeriodicQueryTask.taskName, + PeriodicQueryTask[F](notification), + PeriodicQueryTask.onCancel[F] + ) + ) + .withTask( + JobTask.json( + PeriodicDueItemsTask.taskName, + PeriodicDueItemsTask[F](notification), + PeriodicDueItemsTask.onCancel[F] + ) + ) .resource psch <- PeriodicScheduler.create( cfg.periodicScheduler, @@ -271,7 +296,17 @@ object JoexAppImpl { pstore, joex ) - app = new JoexAppImpl(cfg, store, queue, pubSubT, pstore, termSignal, sch, psch) + app = new JoexAppImpl( + cfg, + store, + queue, + pubSubT, + pstore, + termSignal, + notificationMod, + sch, + psch + ) appR <- Resource.make(app.init.map(_ => app))(_.initShutdown) } yield appR diff --git a/modules/joex/src/main/scala/docspell/joex/notify/PeriodicDueItemsTask.scala b/modules/joex/src/main/scala/docspell/joex/notify/PeriodicDueItemsTask.scala new file mode 100644 index 00000000..312b80e2 --- /dev/null +++ b/modules/joex/src/main/scala/docspell/joex/notify/PeriodicDueItemsTask.scala @@ -0,0 +1,106 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.joex.notify + +import cats.data.NonEmptyList +import cats.effect._ +import cats.implicits._ + +import docspell.backend.ops.ONotification +import docspell.common._ +import docspell.joex.scheduler.Context +import docspell.joex.scheduler.Task +import docspell.notification.api.EventContext +import docspell.notification.api.NotificationChannel +import docspell.notification.api.PeriodicDueItemsArgs +import docspell.query.Date +import docspell.query.ItemQuery._ +import docspell.query.ItemQueryDsl._ +import docspell.store.qb.Batch +import docspell.store.queries.ListItem +import docspell.store.queries.{QItem, Query} + +object PeriodicDueItemsTask { + val taskName = PeriodicDueItemsArgs.taskName + + type Args = PeriodicDueItemsArgs + + def onCancel[F[_]]: Task[F, Args, Unit] = + Task.log(_.warn(s"Cancelling ${taskName.id} task")) + + def apply[F[_]: Sync](notificationOps: ONotification[F]): Task[F, Args, Unit] = + Task { ctx => + val limit = 7 + Timestamp.current[F].flatMap { now => + withItems(ctx, limit, now) { items => + withEventContext(ctx, items, limit, now) { eventCtx => + withChannel(ctx, notificationOps) { channels => + notificationOps.sendMessage(ctx.logger, eventCtx, channels) + } + } + } + } + } + + def withChannel[F[_]: Sync](ctx: Context[F, Args], ops: ONotification[F])( + cont: Vector[NotificationChannel] => F[Unit] + ): F[Unit] = + TaskOperations.withChannel(ctx.logger, ctx.args.channel, ops)(cont) + + def withItems[F[_]: Sync](ctx: Context[F, Args], limit: Int, now: Timestamp)( + cont: Vector[ListItem] => F[Unit] + ): F[Unit] = { + val rightDate = Date((now + Duration.days(ctx.args.remindDays.toLong)).toMillis) + val q = + Query + .all(ctx.args.account) + .withOrder(orderAsc = _.dueDate) + .withFix(_.copy(query = Expr.ValidItemStates.some)) + .withCond(_ => + Query.QueryExpr( + Attr.DueDate <= rightDate &&? + ctx.args.daysBack.map(back => + Attr.DueDate >= Date((now - Duration.days(back.toLong)).toMillis) + ) &&? + NonEmptyList + .fromList(ctx.args.tagsInclude) + .map(ids => Q.tagIdsEq(ids.map(_.id))) &&? + NonEmptyList + .fromList(ctx.args.tagsExclude) + .map(ids => Q.tagIdsIn(ids.map(_.id)).negate) + ) + ) + + for { + res <- + ctx.store + .transact( + QItem + .findItems(q, now.toUtcDate, 0, Batch.limit(limit)) + .take(limit.toLong) + ) + .compile + .toVector + _ <- cont(res) + } yield () + } + + def withEventContext[F[_]]( + ctx: Context[F, Args], + items: Vector[ListItem], + limit: Int, + now: Timestamp + )(cont: EventContext => F[Unit]): F[Unit] = + TaskOperations.withEventContext( + ctx.logger, + ctx.args.account, + ctx.args.baseUrl, + items, + limit, + now + )(cont) +} diff --git a/modules/joex/src/main/scala/docspell/joex/notify/PeriodicQueryTask.scala b/modules/joex/src/main/scala/docspell/joex/notify/PeriodicQueryTask.scala new file mode 100644 index 00000000..76b19be8 --- /dev/null +++ b/modules/joex/src/main/scala/docspell/joex/notify/PeriodicQueryTask.scala @@ -0,0 +1,84 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.joex.notify + +import cats.effect._ +import cats.implicits._ + +import docspell.backend.ops.ONotification +import docspell.common._ +import docspell.joex.scheduler.Context +import docspell.joex.scheduler.Task +import docspell.notification.api.EventContext +import docspell.notification.api.NotificationChannel +import docspell.notification.api.PeriodicQueryArgs +import docspell.query.ItemQueryParser +import docspell.store.qb.Batch +import docspell.store.queries.ListItem +import docspell.store.queries.{QItem, Query} + +object PeriodicQueryTask { + val taskName = PeriodicQueryArgs.taskName + + type Args = PeriodicQueryArgs + + def onCancel[F[_]]: Task[F, Args, Unit] = + Task.log(_.warn(s"Cancelling ${taskName.id} task")) + + def apply[F[_]: Sync](notificationOps: ONotification[F]): Task[F, Args, Unit] = + Task { ctx => + val limit = 7 + Timestamp.current[F].flatMap { now => + withItems(ctx, limit, now) { items => + withEventContext(ctx, items, limit, now) { eventCtx => + withChannel(ctx, notificationOps) { channels => + notificationOps.sendMessage(ctx.logger, eventCtx, channels) + } + } + } + } + } + + def withChannel[F[_]: Sync](ctx: Context[F, Args], ops: ONotification[F])( + cont: Vector[NotificationChannel] => F[Unit] + ): F[Unit] = + TaskOperations.withChannel(ctx.logger, ctx.args.channel, ops)(cont) + + def withItems[F[_]: Sync](ctx: Context[F, Args], limit: Int, now: Timestamp)( + cont: Vector[ListItem] => F[Unit] + ): F[Unit] = + ItemQueryParser.parse(ctx.args.query.query) match { + case Right(q) => + val query = Query(Query.Fix(ctx.args.account, Some(q.expr), None)) + val items = ctx.store + .transact(QItem.findItems(query, now.toUtcDate, 0, Batch.limit(limit))) + .compile + .to(Vector) + + items.flatMap(cont) + case Left(err) => + ctx.logger.error( + s"Item query is invalid, stopping: ${ctx.args.query} - ${err.render}" + ) + } + + def withEventContext[F[_]]( + ctx: Context[F, Args], + items: Vector[ListItem], + limit: Int, + now: Timestamp + )(cont: EventContext => F[Unit]): F[Unit] = + TaskOperations.withEventContext( + ctx.logger, + ctx.args.account, + ctx.args.baseUrl, + items, + limit, + now + )(cont) + +} diff --git a/modules/joex/src/main/scala/docspell/joex/notify/TaskOperations.scala b/modules/joex/src/main/scala/docspell/joex/notify/TaskOperations.scala new file mode 100644 index 00000000..e7cc7b71 --- /dev/null +++ b/modules/joex/src/main/scala/docspell/joex/notify/TaskOperations.scala @@ -0,0 +1,64 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.joex.notify + +import cats.data.NonEmptyList +import cats.effect._ +import cats.implicits._ + +import docspell.backend.ops.ONotification +import docspell.common._ +import docspell.notification.api.ChannelOrRef +import docspell.notification.api.Event +import docspell.notification.api.EventContext +import docspell.notification.api.NotificationChannel +import docspell.notification.impl.context.ItemSelectionCtx +import docspell.store.queries.ListItem + +trait TaskOperations { + + def withChannel[F[_]: Sync]( + logger: Logger[F], + channel: ChannelOrRef, + ops: ONotification[F] + )( + cont: Vector[NotificationChannel] => F[Unit] + ): F[Unit] = { + val channels = channel match { + case Right(ch) => ops.mkNotificationChannel(ch) + case Left(ref) => ops.findNotificationChannel(ref) + } + channels.flatMap { ch => + if (ch.isEmpty) + logger.error(s"No channels found for the given data: ${channel}") + else cont(ch) + } + } + + def withEventContext[F[_]]( + logger: Logger[F], + account: AccountId, + baseUrl: Option[LenientUri], + items: Vector[ListItem], + limit: Int, + now: Timestamp + )(cont: EventContext => F[Unit]): F[Unit] = + NonEmptyList.fromFoldable(items) match { + case Some(nel) => + val more = items.size >= limit + val eventCtx = ItemSelectionCtx( + Event.ItemSelection(account, nel.map(_.id), more, baseUrl), + ItemSelectionCtx.Data + .create(account, items, baseUrl, more, now) + ) + cont(eventCtx) + case None => + logger.info(s"The query selected no items. Notification aborted") + } +} + +object TaskOperations extends TaskOperations diff --git a/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerBuilder.scala b/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerBuilder.scala index cc09f7da..cc5cef12 100644 --- a/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerBuilder.scala +++ b/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerBuilder.scala @@ -11,6 +11,7 @@ import cats.effect.std.Semaphore import cats.implicits._ import fs2.concurrent.SignallingRef +import docspell.notification.api.EventSink import docspell.pubsub.api.PubSubT import docspell.store.Store import docspell.store.queue.JobQueue @@ -21,7 +22,8 @@ case class SchedulerBuilder[F[_]: Async]( store: Store[F], queue: Resource[F, JobQueue[F]], logSink: LogSink[F], - pubSub: PubSubT[F] + pubSub: PubSubT[F], + eventSink: EventSink[F] ) { def withConfig(cfg: SchedulerConfig): SchedulerBuilder[F] = @@ -45,6 +47,9 @@ case class SchedulerBuilder[F[_]: Async]( def withPubSub(pubSubT: PubSubT[F]): SchedulerBuilder[F] = copy(pubSub = pubSubT) + def withEventSink(sink: EventSink[F]): SchedulerBuilder[F] = + copy(eventSink = sink) + def serve: Resource[F, Scheduler[F]] = resource.evalMap(sch => Async[F].start(sch.start.compile.drain).map(_ => sch)) @@ -58,6 +63,7 @@ case class SchedulerBuilder[F[_]: Async]( config, jq, pubSub, + eventSink, tasks, store, logSink, @@ -83,7 +89,8 @@ object SchedulerBuilder { store, JobQueue(store), LogSink.db[F](store), - PubSubT.noop[F] + PubSubT.noop[F], + EventSink.silent[F] ) } diff --git a/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerImpl.scala b/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerImpl.scala index b403b59c..9411056d 100644 --- a/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerImpl.scala +++ b/modules/joex/src/main/scala/docspell/joex/scheduler/SchedulerImpl.scala @@ -17,6 +17,8 @@ import docspell.backend.msg.JobDone import docspell.common._ import docspell.common.syntax.all._ import docspell.joex.scheduler.SchedulerImpl._ +import docspell.notification.api.Event +import docspell.notification.api.EventSink import docspell.pubsub.api.PubSubT import docspell.store.Store import docspell.store.queries.QJob @@ -29,6 +31,7 @@ final class SchedulerImpl[F[_]: Async]( val config: SchedulerConfig, queue: JobQueue[F], pubSub: PubSubT[F], + eventSink: EventSink[F], tasks: JobTaskRegistry[F], store: Store[F], logSink: LogSink[F], @@ -206,6 +209,17 @@ final class SchedulerImpl[F[_]: Async]( JobDone.topic, JobDone(job.id, job.group, job.task, job.args, finalState) ) + _ <- eventSink.offer( + Event.JobDone( + job.id, + job.group, + job.task, + job.args, + job.state, + job.subject, + job.submitter + ) + ) } yield () def onStart(job: RJob): F[Unit] = diff --git a/modules/joexapi/src/main/resources/joex-openapi.yml b/modules/joexapi/src/main/resources/joex-openapi.yml index 3477b74b..2ca2da28 100644 --- a/modules/joexapi/src/main/resources/joex-openapi.yml +++ b/modules/joexapi/src/main/resources/joex-openapi.yml @@ -27,6 +27,8 @@ paths: description: | Returns the version and project name and other properties of the build. responses: + 422: + description: BadRequest 200: description: Ok content: @@ -41,6 +43,8 @@ paths: description: | Notifies the job executor to wake up and look for jobs in th queue. responses: + 422: + description: BadRequest 200: description: Ok content: @@ -55,6 +59,8 @@ paths: description: | Returns all jobs this executor is currently executing. responses: + 422: + description: BadRequest 200: description: Ok content: @@ -69,6 +75,8 @@ paths: description: | Gracefully stops the scheduler and also stops the process. responses: + 422: + description: BadRequest 200: description: Ok content: @@ -85,6 +93,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -103,6 +113,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: diff --git a/modules/jsonminiq/src/main/scala/docspell/jsonminiq/Format.scala b/modules/jsonminiq/src/main/scala/docspell/jsonminiq/Format.scala new file mode 100644 index 00000000..2428c19d --- /dev/null +++ b/modules/jsonminiq/src/main/scala/docspell/jsonminiq/Format.scala @@ -0,0 +1,59 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.jsonminiq + +import cats.implicits._ + +/** The inverse to Parser */ +private[jsonminiq] object Format { + + def apply(q: JsonMiniQuery): Either[String, String] = + q match { + case JsonMiniQuery.Empty => Right("") + case JsonMiniQuery.Identity => Right("") + case JsonMiniQuery.Fields(fields) => + Right(fields.toVector.mkString(",")) + + case JsonMiniQuery.Indexes(nums) => + Right(nums.toVector.mkString("(", ",", ")")) + + case JsonMiniQuery.Filter(values, mt) => + formatValue(values.head).map(v => formatMatchType(mt) + v) + + case JsonMiniQuery.Chain(self, next) => + for { + s1 <- apply(self) + s2 <- apply(next) + res = next match { + case _: JsonMiniQuery.Fields => + s1 + "." + s2 + case _ => + s1 + s2 + } + } yield res + + case JsonMiniQuery.Concat(inner) => + inner.toVector.traverse(apply).map(_.mkString("[", " | ", "]")) + + case JsonMiniQuery.Forall(inner) => + inner.toVector.traverse(apply).map(_.mkString("[", " & ", "]")) + } + + def formatValue(v: String): Either[String, String] = + if (v.forall(Parser.isValidSimpleValue)) Right(v) + else if (v.contains("\"") && v.contains("'")) + Left(s"Value cannot use both \" and ': $v") + else if (v.contains("'")) Right(s"\"$v\"") + else Right(s"'$v'") + + def formatMatchType(matchType: JsonMiniQuery.MatchType): String = + matchType match { + case JsonMiniQuery.MatchType.All => "=" + case JsonMiniQuery.MatchType.Any => ":" + case JsonMiniQuery.MatchType.None => "!" + } +} diff --git a/modules/jsonminiq/src/main/scala/docspell/jsonminiq/JsonMiniQuery.scala b/modules/jsonminiq/src/main/scala/docspell/jsonminiq/JsonMiniQuery.scala new file mode 100644 index 00000000..6de84081 --- /dev/null +++ b/modules/jsonminiq/src/main/scala/docspell/jsonminiq/JsonMiniQuery.scala @@ -0,0 +1,245 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.jsonminiq + +import cats.Monoid +import cats.data.NonEmptyVector +import cats.implicits._ + +import io.circe.Decoder +import io.circe.Encoder +import io.circe.Json.Folder +import io.circe.{Json, JsonNumber, JsonObject} + +/** Cteate a predicate for a Json value. */ +sealed trait JsonMiniQuery { self => + + def apply(json: Json): Vector[Json] + + def >>(next: JsonMiniQuery): JsonMiniQuery = + JsonMiniQuery.Chain(self, next) + + def ++(other: JsonMiniQuery): JsonMiniQuery = + JsonMiniQuery.Concat(NonEmptyVector.of(self, other)) + + def thenAny(other: JsonMiniQuery, more: JsonMiniQuery*): JsonMiniQuery = + self >> JsonMiniQuery.or(other, more: _*) + + def thenAll(other: JsonMiniQuery, more: JsonMiniQuery*): JsonMiniQuery = + self >> JsonMiniQuery.and(other, more: _*) + + def at(field: String, fields: String*): JsonMiniQuery = + self >> JsonMiniQuery.Fields(NonEmptyVector(field, fields.toVector)) + + def at(index: Int, indexes: Int*): JsonMiniQuery = + self >> JsonMiniQuery.Indexes(NonEmptyVector(index, indexes.toVector)) + + def isAll(value: String, values: String*): JsonMiniQuery = + self >> JsonMiniQuery.Filter( + NonEmptyVector(value, values.toVector), + JsonMiniQuery.MatchType.All + ) + + def isAny(value: String, values: String*): JsonMiniQuery = + self >> JsonMiniQuery.Filter( + NonEmptyVector(value, values.toVector), + JsonMiniQuery.MatchType.Any + ) + + def is(value: String): JsonMiniQuery = + isAny(value) + + def &&(other: JsonMiniQuery): JsonMiniQuery = + JsonMiniQuery.and(self, other) + + def ||(other: JsonMiniQuery): JsonMiniQuery = + self ++ other + + def matches(json: Json): Boolean = + apply(json).nonEmpty + + def notMatches(json: Json): Boolean = + !matches(json) + + /** Returns a string representation of this that can be parsed back to this value. + * Formatting can fail, because not everything is supported. The idea is that every + * value that was parsed, can be formatted. + */ + def asString: Either[String, String] = + Format(this) + + def unsafeAsString: String = + asString.fold(sys.error, identity) +} + +object JsonMiniQuery { + + def parse(str: String): Either[String, JsonMiniQuery] = + Parser.query + .parseAll(str) + .leftMap(err => + s"Unexpected input at ${err.failedAtOffset}. Expected: ${err.expected.toList.mkString(", ")}" + ) + + def unsafeParse(str: String): JsonMiniQuery = + parse(str).fold(sys.error, identity) + + val root: JsonMiniQuery = Identity + val id: JsonMiniQuery = Identity + val none: JsonMiniQuery = Empty + + def and(self: JsonMiniQuery, more: JsonMiniQuery*): JsonMiniQuery = + Forall(NonEmptyVector(self, more.toVector)) + + def or(self: JsonMiniQuery, more: JsonMiniQuery*): JsonMiniQuery = + Concat(NonEmptyVector(self, more.toVector)) + + // --- impl + + case object Identity extends JsonMiniQuery { + def apply(json: Json) = Vector(json) + override def >>(next: JsonMiniQuery): JsonMiniQuery = next + } + + case object Empty extends JsonMiniQuery { + def apply(json: Json) = Vector.empty + override def at(field: String, fields: String*): JsonMiniQuery = this + override def at(field: Int, fields: Int*): JsonMiniQuery = this + override def isAll(value: String, values: String*) = this + override def isAny(value: String, values: String*) = this + override def >>(next: JsonMiniQuery): JsonMiniQuery = this + override def ++(other: JsonMiniQuery): JsonMiniQuery = other + } + + private def unwrapArrays(json: Vector[Json]): Vector[Json] = + json.foldLeft(Vector.empty[Json]) { (res, el) => + el.asArray.map(x => res ++ x).getOrElse(res :+ el) + } + + final case class Fields(names: NonEmptyVector[String]) extends JsonMiniQuery { + def apply(json: Json) = json.foldWith(folder) + + private val folder: Folder[Vector[Json]] = new Folder[Vector[Json]] { + def onNull = Vector.empty + def onBoolean(value: Boolean) = Vector.empty + def onNumber(value: JsonNumber) = Vector.empty + def onString(value: String) = Vector.empty + def onArray(value: Vector[Json]) = + unwrapArrays(value.flatMap(inner => inner.foldWith(this))) + def onObject(value: JsonObject) = + unwrapArrays(names.toVector.flatMap(value.apply)) + } + } + final case class Indexes(indexes: NonEmptyVector[Int]) extends JsonMiniQuery { + def apply(json: Json) = json.foldWith(folder) + + private val folder: Folder[Vector[Json]] = new Folder[Vector[Json]] { + def onNull = Vector.empty + def onBoolean(value: Boolean) = Vector.empty + def onNumber(value: JsonNumber) = Vector.empty + def onString(value: String) = Vector.empty + def onArray(value: Vector[Json]) = + unwrapArrays(indexes.toVector.flatMap(i => value.get(i.toLong))) + def onObject(value: JsonObject) = + Vector.empty + } + } + + sealed trait MatchType { + def monoid: Monoid[Boolean] + } + object MatchType { + case object Any extends MatchType { + val monoid = Monoid.instance(false, _ || _) + } + case object All extends MatchType { + val monoid = Monoid.instance(true, _ && _) + } + case object None extends MatchType { // = not Any + val monoid = Monoid.instance(true, _ && !_) + } + } + + final case class Filter( + values: NonEmptyVector[String], + combine: MatchType + ) extends JsonMiniQuery { + def apply(json: Json): Vector[Json] = + json.asArray match { + case Some(arr) => + unwrapArrays(arr.filter(el => el.foldWith(folder(combine)))) + case None => + if (json.foldWith(folder(combine))) unwrapArrays(Vector(json)) + else Vector.empty + } + + private val anyMatch = folder(MatchType.Any) + + private def folder(matchType: MatchType): Folder[Boolean] = new Folder[Boolean] { + def onNull = + onString("*null*") + + def onBoolean(value: Boolean) = + values + .map(_.equalsIgnoreCase(value.toString)) + .fold(matchType.monoid) + + def onNumber(value: JsonNumber) = + values + .map( + _.equalsIgnoreCase( + value.toLong.map(_.toString).getOrElse(value.toDouble.toString) + ) + ) + .fold(matchType.monoid) + + def onString(value: String) = + values + .map(_.equalsIgnoreCase(value)) + .fold(matchType.monoid) + + def onArray(value: Vector[Json]) = + value + .map(inner => inner.foldWith(anyMatch)) + .fold(matchType.monoid.empty)(matchType.monoid.combine) + + def onObject(value: JsonObject) = false + } + } + + final case class Chain(self: JsonMiniQuery, next: JsonMiniQuery) extends JsonMiniQuery { + def apply(json: Json): Vector[Json] = + next(Json.fromValues(self(json))) + } + + final case class Concat(qs: NonEmptyVector[JsonMiniQuery]) extends JsonMiniQuery { + def apply(json: Json): Vector[Json] = + qs.toVector.flatMap(_.apply(json)) + } + + final case class Forall(qs: NonEmptyVector[JsonMiniQuery]) extends JsonMiniQuery { + def apply(json: Json): Vector[Json] = + combineWhenNonEmpty(qs.toVector.map(_.apply(json)), Vector.empty) + + @annotation.tailrec + private def combineWhenNonEmpty( + values: Vector[Vector[Json]], + result: Vector[Json] + ): Vector[Json] = + values.headOption match { + case Some(v) if v.nonEmpty => combineWhenNonEmpty(values.tail, result ++ v) + case Some(_) => Vector.empty + case None => result + } + } + + implicit val jsonDecoder: Decoder[JsonMiniQuery] = + Decoder.decodeString.emap(parse) + + implicit val jsonEncoder: Encoder[JsonMiniQuery] = + Encoder.encodeString.contramap(_.unsafeAsString) +} diff --git a/modules/jsonminiq/src/main/scala/docspell/jsonminiq/Parser.scala b/modules/jsonminiq/src/main/scala/docspell/jsonminiq/Parser.scala new file mode 100644 index 00000000..e0b2ca2d --- /dev/null +++ b/modules/jsonminiq/src/main/scala/docspell/jsonminiq/Parser.scala @@ -0,0 +1,105 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.jsonminiq + +import cats.data.NonEmptyVector +import cats.parse.{Parser => P, Parser0 => P0} + +import docspell.jsonminiq.JsonMiniQuery.{Identity => JQ} + +private[jsonminiq] object Parser { + + // a[,b] -> at(string) + // (1[,2,3]) -> at(int) + // :b -> isAny(b) + // =b -> isAll(b) + // [F & G] -> F && G + // [F | G] -> F || G + + private[this] val whitespace: P[Unit] = P.charIn(" \t\r\n").void + private[this] val extraFieldChars = "_-".toSet + private[this] val dontUse = "\"'\\[]()&|".toSet + + private[this] val ws0: P0[Unit] = whitespace.rep0.void + + private[this] val parenOpen: P[Unit] = P.char('(') *> ws0 + private[this] val parenClose: P[Unit] = ws0.with1 *> P.char(')') + private[this] val bracketOpen: P[Unit] = P.char('[') *> ws0 + private[this] val bracketClose: P[Unit] = ws0.with1 *> P.char(']') + private[this] val dot: P[Unit] = P.char('.') + private[this] val comma: P[Unit] = P.char(',') + private[this] val andSym: P[Unit] = ws0.with1 *> P.char('&') <* ws0 + private[this] val orSym: P[Unit] = ws0.with1 *> P.char('|') <* ws0 + private[this] val squote: P[Unit] = P.char('\'') + private[this] val dquote: P[Unit] = P.char('"') + private[this] val allOp: P[JsonMiniQuery.MatchType] = + P.char('=').as(JsonMiniQuery.MatchType.All) + private[this] val noneOp: P[JsonMiniQuery.MatchType] = + P.char('!').as(JsonMiniQuery.MatchType.None) + + def isValidSimpleValue(c: Char): Boolean = + c > ' ' && !dontUse.contains(c) + + val value: P[String] = { + val simpleString: P[String] = + P.charsWhile(isValidSimpleValue) + + val quotedString: P[String] = { + val single: P[String] = + squote *> P.charsWhile0(_ != '\'') <* squote + + val double: P[String] = + dquote *> P.charsWhile0(_ != '"') <* dquote + + single | double + } + + simpleString | quotedString + } + + val field: P[String] = + P.charsWhile(c => c.isLetterOrDigit || extraFieldChars.contains(c)) + val posNum: P[Int] = P.charsWhile(_.isDigit).map(_.toInt).filter(_ >= 0) + + val fieldSelect1: P[JsonMiniQuery] = + field.repSep(comma).map(nel => JQ.at(nel.head, nel.tail: _*)) + + val arraySelect1: P[JsonMiniQuery] = { + val nums = posNum.repSep(1, comma) + parenOpen.soft *> nums.map(f => JQ.at(f.head, f.tail: _*)) <* parenClose + } + + val match1: P[JsonMiniQuery] = + ((allOp | noneOp) ~ value).map { case (op, v) => + JsonMiniQuery.Filter(NonEmptyVector.of(v), op) + } + + val segment = { + val firstSegment = fieldSelect1 | arraySelect1 | match1 + val nextSegment = (dot *> fieldSelect1) | arraySelect1 | match1 + + (firstSegment ~ nextSegment.rep0).map { case (head, tail) => + tail.foldLeft(head)(_ >> _) + } + } + + def combine(inner: P[JsonMiniQuery]): P[JsonMiniQuery] = { + val or = inner.repSep(orSym).map(_.reduceLeft(_ || _)) + val and = inner.repSep(andSym).map(_.reduceLeft(_ && _)) + + and + .between(bracketOpen, bracketClose) + .backtrack + .orElse(or.between(bracketOpen, bracketClose)) + } + + val query: P[JsonMiniQuery] = + P.recursive[JsonMiniQuery] { recurse => + val comb = combine(recurse) + P.oneOf(segment :: comb :: Nil).rep.map(_.reduceLeft(_ >> _)) + } +} diff --git a/modules/jsonminiq/src/test/scala/docspell/jsonminiq/Fixtures.scala b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/Fixtures.scala new file mode 100644 index 00000000..07144171 --- /dev/null +++ b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/Fixtures.scala @@ -0,0 +1,76 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.jsonminiq + +import cats.parse.{Parser => P} + +import io.circe.Json + +trait Fixtures { + + val sampleEvent: Json = + parseJson( + """{ + | "eventType": "TagsChanged", + | "account": { + | "collective": "demo", + | "user": "demo", + | "login": "demo" + | }, + | "content": { + | "account": "demo", + | "items": [ + | { + | "id": "4PvMM4m7Fwj-FsPRGxYt9zZ-uUzi35S2rEX-usyDEVyheR8", + | "name": "MapleSirupLtd_202331.pdf", + | "dateMillis": 1633557740733, + | "date": "2021-10-06", + | "direction": "incoming", + | "state": "confirmed", + | "dueDateMillis": 1639173740733, + | "dueDate": "2021-12-10", + | "source": "webapp", + | "overDue": false, + | "dueIn": "in 3 days", + | "corrOrg": "Acme AG", + | "notes": null + | } + | ], + | "added": [ + | { + | "id": "Fy4VC6hQwcL-oynrHaJg47D-Q5RiQyB5PQP-N5cFJ368c4N", + | "name": "Invoice", + | "category": "doctype" + | }, + | { + | "id": "7zaeU6pqVym-6Je3Q36XNG2-ZdBTFSVwNjc-pJRXciTMP3B", + | "name": "Grocery", + | "category": "expense" + | } + | ], + | "removed": [ + | { + | "id": "GbXgszdjBt4-zrzuLHoUx7N-RMFatC8CyWt-5dsBCvxaEuW", + | "name": "Receipt", + | "category": "doctype" + | } + | ], + | "itemUrl": "http://localhost:7880/app/item" + | } + |}""".stripMargin + ) + + def parseJson(str: String): Json = + io.circe.parser.parse(str).fold(throw _, identity) + + def parseP[A](p: P[A], str: String): A = + p.parseAll(str.trim()) + .fold(e => sys.error(s"${e.getClass}: $e"), identity) + + def parse(str: String): JsonMiniQuery = parseP(Parser.query, str) + +} diff --git a/modules/jsonminiq/src/test/scala/docspell/jsonminiq/FormatTest.scala b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/FormatTest.scala new file mode 100644 index 00000000..27dd4c3c --- /dev/null +++ b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/FormatTest.scala @@ -0,0 +1,52 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.jsonminiq + +import docspell.jsonminiq.JsonMiniQuery.{Identity => JQ} + +import munit._ + +class FormatTest extends FunSuite with Fixtures { + + def format(q: JsonMiniQuery): String = + q.unsafeAsString + + test("field selects") { + assertEquals( + format(JQ.at("content").at("added", "removed").at("name")), + "content.added,removed.name" + ) + } + + test("array select") { + assertEquals(format(JQ.at("content").at(1, 2).at("name")), "content(1,2).name") + } + + test("anyMatch / allMatch") { + assertEquals(format(JQ.isAny("in voice")), ":'in voice'") + assertEquals(format(JQ.isAll("invoice")), "=invoice") + + assertEquals(format(JQ.at("name").isAll("invoice")), "name=invoice") + assertEquals(format(JQ.at("name").isAny("invoice")), "name:invoice") + } + + test("and / or") { + assertEquals( + format((JQ.at("c") >> JQ.isAll("d")) || (JQ.at("e") >> JQ.isAll("f"))), + "[c=d | e=f]" + ) + + assertEquals( + format( + (JQ.at("a").isAll("1")) || ( + (JQ.at("b").isAll("2")) && (JQ.at("c").isAll("3")) + ) + ), + "[a=1 | [b=2 & c=3]]" + ) + } +} diff --git a/modules/jsonminiq/src/test/scala/docspell/jsonminiq/JsonMiniQueryTest.scala b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/JsonMiniQueryTest.scala new file mode 100644 index 00000000..181ac835 --- /dev/null +++ b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/JsonMiniQueryTest.scala @@ -0,0 +1,161 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.jsonminiq + +import docspell.jsonminiq.JsonMiniQuery.{Identity => JQ} + +import io.circe.Encoder +import io.circe.Json +import io.circe.syntax._ +import munit._ + +class JsonMiniQueryTest extends FunSuite with Fixtures { + + def values[T: Encoder](v1: T, vn: T*): Vector[Json] = + (v1 +: vn.toVector).map(_.asJson) + + test("combine values on same level") { + val q = JQ + .at("content") + .at("added", "removed") + .at("name") + + assertEquals(q(sampleEvent), values("Invoice", "Grocery", "Receipt")) + } + + test("combine values from different levels") { + val q1 = JQ.at("account") + val q2 = JQ.at("removed").at("name") + val q = JQ.at("content") >> (q1 ++ q2) + + assertEquals(q(sampleEvent), values("demo", "Receipt")) + } + + test("filter single value") { + val q = JQ.at("account").at("login").isAll("demo") + assertEquals(q(sampleEvent), values("demo")) + + val q2 = JQ.at("account").at("login").isAll("james") + assertEquals(q2(sampleEvent), Vector.empty) + } + + test("combine filters") { + val q1 = JQ.at("account").at("login").isAll("demo") + val q2 = JQ.at("eventType").isAll("tagschanged") + val q3 = JQ.at("content").at("added", "removed").at("name").isAny("invoice") + + val q = q1 && q2 && q3 + assertEquals( + q(sampleEvent), + values("demo", "TagsChanged", "Invoice") + ) + + val q11 = JQ.at("account").at("login").isAll("not-exists") + val r = q11 && q2 && q3 + assertEquals(r(sampleEvent), Vector.empty) + } + + //content.[added,removed].(category=expense & name=grocery) + test("combine fields and filter") { + val andOk = JQ.at("content").at("added", "removed") >> + (JQ.at("name").is("grocery") && JQ.at("category").is("expense")) + assert(andOk.matches(sampleEvent)) + + val andNotOk = JQ.at("content").at("added", "removed") >> + (JQ.at("name").is("grocery") && JQ.at("category").is("notexist")) + assert(andNotOk.notMatches(sampleEvent)) + + val orOk = JQ.at("content").at("added", "removed") >> + (JQ.at("name").is("grocery") || JQ.at("category").is("notexist")) + assert(orOk.matches(sampleEvent)) + } + + test("thenAny combine via or") { + val q = JQ + .at("content") + .thenAny( + JQ.is("not this"), + JQ.at("account"), + JQ.at("oops") + ) + assert(q.matches(sampleEvent)) + } + + test("thenAll combine via and (1)") { + val q = JQ + .at("content") + .thenAll( + JQ.is("not this"), + JQ.at("account"), + JQ.at("oops") + ) + assert(q.notMatches(sampleEvent)) + } + + test("thenAll combine via and (2)") { + val q = JQ + .at("content") + .thenAll( + JQ.at("items").at("date").is("2021-10-06"), + JQ.at("account"), + JQ.at("added").at("name") + ) + assert(q.matches(sampleEvent)) + + // equivalent + val q2 = JQ.at("content") >> ( + JQ.at("items").at("date").is("2021-10-06") && + JQ.at("account") && + JQ.at("added").at("name") + ) + assert(q2.matches(sampleEvent)) + } + + test("test for null/not null") { + val q1 = parse("content.items.notes=*null*") + assert(q1.matches(sampleEvent)) + + val q2 = parse("content.items.notes=bla") + assert(q2.notMatches(sampleEvent)) + + val q3 = parse("content.items.notes!*null*") + assert(q3.notMatches(sampleEvent)) + } + + test("more real expressions") { + val q = parse("content.added,removed[name=invoice | category=expense]") + assert(q.matches(sampleEvent)) + } + + test("examples") { + val q0 = parse("a.b.x,y") + val json = parseJson( + """[{"a": {"b": {"x": 1, "y":2}}, "v": 0}, {"a": {"b": {"y": 9, "b": 2}}, "z": 0}]""" + ) + assertEquals(q0(json), values(1, 2, 9)) + + val q1 = parse("a(0,2)") + val json1 = parseJson("""[{"a": [10,9,8,7]}, {"a": [1,2,3,4]}]""") + assertEquals(q1(json1), values(10, 8)) + + val q2 = parse("=blue") + val json2 = parseJson("""["blue", "green", "red"]""") + assertEquals(q2(json2), values("blue")) + + val q3 = parse("color=blue") + val json3 = parseJson( + """[{"color": "blue", "count": 2}, {"color": "blue", "count": 1}, {"color": "blue", "count": 3}]""" + ) + assertEquals(q3(json3), values("blue", "blue", "blue")) + + val q4 = parse("[count=6 | name=max]") + val json4 = parseJson( + """[{"name":"max", "count":4}, {"name":"me", "count": 3}, {"name":"max", "count": 3}]""" + ) + println(q4(json4)) + } +} diff --git a/modules/jsonminiq/src/test/scala/docspell/jsonminiq/ParserTest.scala b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/ParserTest.scala new file mode 100644 index 00000000..4be75c11 --- /dev/null +++ b/modules/jsonminiq/src/test/scala/docspell/jsonminiq/ParserTest.scala @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.jsonminiq + +import docspell.jsonminiq.JsonMiniQuery.{Identity => JQ} + +import munit._ + +class ParserTest extends FunSuite with Fixtures { + + test("field selects") { + assertEquals( + parse("content.added,removed.name"), + JQ.at("content").at("added", "removed").at("name") + ) + } + + test("array select") { + assertEquals(parse("content(1,2).name"), JQ.at("content").at(1, 2).at("name")) + } + + test("values") { + assertEquals(parseP(Parser.value, "\"in voice\""), "in voice") + assertEquals(parseP(Parser.value, "'in voice'"), "in voice") + assertEquals(parseP(Parser.value, "invoice"), "invoice") + intercept[Throwable](parseP(Parser.value, "in voice")) + } + + test("anyMatch / allMatch") { + assertEquals(parse("='invoice'"), JQ.isAll("invoice")) + assertEquals(parse("=invoice"), JQ.isAll("invoice")) + + assertEquals(parse("name=invoice"), JQ.at("name").isAll("invoice")) + assertEquals(parse("name=\"invoice\""), JQ.at("name").isAll("invoice")) + } + + test("and / or") { + assertEquals( + parse("[c=d | e=f]"), + (JQ.at("c") >> JQ.isAll("d")) || (JQ.at("e") >> JQ.isAll("f")) + ) + + assertEquals( + parse("[a=1 | [b=2 & c=3]]"), + (JQ.at("a") >> JQ.isAll("1")) || ( + (JQ.at("b") >> JQ.isAll("2")) && (JQ.at("c") >> JQ.isAll("3")) + ) + ) + } +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala b/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala new file mode 100644 index 00000000..5de9250e --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala @@ -0,0 +1,112 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.data.{NonEmptyList => Nel} + +import docspell.common._ + +import emil.MailAddress +import io.circe.generic.extras.Configuration +import io.circe.generic.extras.semiauto.{deriveConfiguredDecoder, deriveConfiguredEncoder} +import io.circe.{Decoder, Encoder} + +/** A type for representing channels as stored in the database. */ +sealed trait Channel { + def id: Ident + def channelType: ChannelType + def fold[A]( + f1: Channel.Mail => A, + f2: Channel.Gotify => A, + f3: Channel.Matrix => A, + f4: Channel.Http => A + ): A + def asRef: ChannelRef = ChannelRef(id, channelType) +} + +object Channel { + implicit val jsonConfig = Configuration.default.withDiscriminator("channelType") + + final case class Mail( + id: Ident, + connection: Ident, + recipients: Nel[MailAddress] + ) extends Channel { + val channelType = ChannelType.Mail + def fold[A]( + f1: Mail => A, + f2: Gotify => A, + f3: Matrix => A, + f4: Http => A + ): A = f1(this) + } + + object Mail { + implicit def jsonDecoder(implicit D: Decoder[MailAddress]): Decoder[Mail] = + deriveConfiguredDecoder[Mail] + + implicit def jsonEncoder(implicit E: Encoder[MailAddress]): Encoder[Mail] = + deriveConfiguredEncoder[Mail] + } + + final case class Gotify(id: Ident, url: LenientUri, appKey: Password) extends Channel { + val channelType = ChannelType.Gotify + def fold[A]( + f1: Mail => A, + f2: Gotify => A, + f3: Matrix => A, + f4: Http => A + ): A = f2(this) + } + + object Gotify { + implicit val jsonDecoder: Decoder[Gotify] = + deriveConfiguredDecoder + implicit val jsonEncoder: Encoder[Gotify] = + deriveConfiguredEncoder + } + + final case class Matrix( + id: Ident, + homeServer: LenientUri, + roomId: String, + accessToken: Password + ) extends Channel { + val channelType = ChannelType.Matrix + def fold[A]( + f1: Mail => A, + f2: Gotify => A, + f3: Matrix => A, + f4: Http => A + ): A = f3(this) + } + + object Matrix { + implicit val jsonDecoder: Decoder[Matrix] = deriveConfiguredDecoder + implicit val jsonEncoder: Encoder[Matrix] = deriveConfiguredEncoder + } + + final case class Http(id: Ident, url: LenientUri) extends Channel { + val channelType = ChannelType.Http + def fold[A]( + f1: Mail => A, + f2: Gotify => A, + f3: Matrix => A, + f4: Http => A + ): A = f4(this) + } + + object Http { + implicit val jsonDecoder: Decoder[Http] = deriveConfiguredDecoder + implicit val jsonEncoder: Encoder[Http] = deriveConfiguredEncoder + } + + implicit def jsonDecoder(implicit mc: Decoder[MailAddress]): Decoder[Channel] = + deriveConfiguredDecoder + implicit def jsonEncoder(implicit mc: Encoder[MailAddress]): Encoder[Channel] = + deriveConfiguredEncoder +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/ChannelRef.scala b/modules/notification/api/src/main/scala/docspell/notification/api/ChannelRef.scala new file mode 100644 index 00000000..cfd21d48 --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/ChannelRef.scala @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import docspell.common.Ident + +import io.circe.Decoder +import io.circe.Encoder +import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} + +final case class ChannelRef(id: Ident, channelType: ChannelType) + +object ChannelRef { + + implicit val jsonDecoder: Decoder[ChannelRef] = + deriveDecoder + + implicit val jsonEncoder: Encoder[ChannelRef] = + deriveEncoder +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/ChannelType.scala b/modules/notification/api/src/main/scala/docspell/notification/api/ChannelType.scala new file mode 100644 index 00000000..4403f2be --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/ChannelType.scala @@ -0,0 +1,46 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.data.{NonEmptyList => Nel} + +import io.circe.Decoder +import io.circe.Encoder + +sealed trait ChannelType { self: Product => + + def name: String = + productPrefix +} + +object ChannelType { + + case object Mail extends ChannelType + case object Gotify extends ChannelType + case object Matrix extends ChannelType + case object Http extends ChannelType + + val all: Nel[ChannelType] = + Nel.of(Mail, Gotify, Matrix, Http) + + def fromString(str: String): Either[String, ChannelType] = + str.toLowerCase match { + case "mail" => Right(Mail) + case "gotify" => Right(Gotify) + case "matrix" => Right(Matrix) + case "http" => Right(Http) + case _ => Left(s"Unknown channel type: $str") + } + + def unsafeFromString(str: String): ChannelType = + fromString(str).fold(sys.error, identity) + + implicit val jsonDecoder: Decoder[ChannelType] = + Decoder.decodeString.emap(fromString) + implicit val jsonEncoder: Encoder[ChannelType] = + Encoder.encodeString.contramap(_.name) +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/Event.scala b/modules/notification/api/src/main/scala/docspell/notification/api/Event.scala new file mode 100644 index 00000000..371d4ebe --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/Event.scala @@ -0,0 +1,246 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.data.{NonEmptyList => Nel} +import cats.effect.kernel.Sync +import cats.implicits._ + +import docspell.common._ + +import io.circe.{Decoder, Encoder} + +/** An event generated in the platform. */ +sealed trait Event { + + /** The type of event */ + def eventType: EventType + + /** The user who caused it. */ + def account: AccountId + + /** The base url for generating links. This is dynamic. */ + def baseUrl: Option[LenientUri] +} + +sealed trait EventType { self: Product => + + def name: String = + productPrefix +} + +object EventType { + + def all: Nel[EventType] = + Nel.of( + Event.TagsChanged, + Event.SetFieldValue, + Event.DeleteFieldValue, + Event.ItemSelection, + Event.JobSubmitted, + Event.JobDone + ) + + def fromString(str: String): Either[String, EventType] = + all.find(_.name.equalsIgnoreCase(str)).toRight(s"Unknown event type: $str") + + def unsafeFromString(str: String): EventType = + fromString(str).fold(sys.error, identity) + + implicit val jsonDecoder: Decoder[EventType] = + Decoder.decodeString.emap(fromString) + + implicit val jsonEncoder: Encoder[EventType] = + Encoder.encodeString.contramap(_.name) +} + +object Event { + + /** Event triggered when tags of one or more items have changed */ + final case class TagsChanged( + account: AccountId, + items: Nel[Ident], + added: List[String], + removed: List[String], + baseUrl: Option[LenientUri] + ) extends Event { + val eventType = TagsChanged + } + case object TagsChanged extends EventType { + def partial( + items: Nel[Ident], + added: List[String], + removed: List[String] + ): (AccountId, Option[LenientUri]) => TagsChanged = + (acc, url) => TagsChanged(acc, items, added, removed, url) + + def sample[F[_]: Sync]( + account: AccountId, + baseUrl: Option[LenientUri] + ): F[TagsChanged] = + for { + id1 <- Ident.randomId[F] + id2 <- Ident.randomId[F] + id3 <- Ident.randomId[F] + } yield TagsChanged(account, Nel.of(id1), List(id2.id), List(id3.id), baseUrl) + } + + /** Event triggered when a custom field on an item changes. */ + final case class SetFieldValue( + account: AccountId, + items: Nel[Ident], + field: Ident, + value: String, + baseUrl: Option[LenientUri] + ) extends Event { + val eventType = SetFieldValue + } + case object SetFieldValue extends EventType { + def partial( + items: Nel[Ident], + field: Ident, + value: String + ): (AccountId, Option[LenientUri]) => SetFieldValue = + (acc, url) => SetFieldValue(acc, items, field, value, url) + + def sample[F[_]: Sync]( + account: AccountId, + baseUrl: Option[LenientUri] + ): F[SetFieldValue] = + for { + id1 <- Ident.randomId[F] + id2 <- Ident.randomId[F] + } yield SetFieldValue(account, Nel.of(id1), id2, "10.15", baseUrl) + } + + final case class DeleteFieldValue( + account: AccountId, + items: Nel[Ident], + field: Ident, + baseUrl: Option[LenientUri] + ) extends Event { + val eventType = DeleteFieldValue + } + case object DeleteFieldValue extends EventType { + def partial( + items: Nel[Ident], + field: Ident + ): (AccountId, Option[LenientUri]) => DeleteFieldValue = + (acc, url) => DeleteFieldValue(acc, items, field, url) + + def sample[F[_]: Sync]( + account: AccountId, + baseUrl: Option[LenientUri] + ): F[DeleteFieldValue] = + for { + id1 <- Ident.randomId[F] + id2 <- Ident.randomId[F] + } yield DeleteFieldValue(account, Nel.of(id1), id2, baseUrl) + + } + + /** Some generic list of items, chosen by a user. */ + final case class ItemSelection( + account: AccountId, + items: Nel[Ident], + more: Boolean, + baseUrl: Option[LenientUri] + ) extends Event { + val eventType = ItemSelection + } + + case object ItemSelection extends EventType { + def sample[F[_]: Sync]( + account: AccountId, + baseUrl: Option[LenientUri] + ): F[ItemSelection] = + for { + id1 <- Ident.randomId[F] + id2 <- Ident.randomId[F] + } yield ItemSelection(account, Nel.of(id1, id2), true, baseUrl) + } + + /** Event when a new job is added to the queue */ + final case class JobSubmitted( + jobId: Ident, + group: Ident, + task: Ident, + args: String, + state: JobState, + subject: String, + submitter: Ident + ) extends Event { + val eventType = JobSubmitted + val baseUrl = None + def account: AccountId = AccountId(group, submitter) + } + case object JobSubmitted extends EventType { + def sample[F[_]: Sync](account: AccountId): F[JobSubmitted] = + for { + id <- Ident.randomId[F] + ev = JobSubmitted( + id, + account.collective, + Ident.unsafe("process-something-task"), + "", + JobState.running, + "Process 3 files", + account.user + ) + } yield ev + } + + /** Event when a job is finished (in final state). */ + final case class JobDone( + jobId: Ident, + group: Ident, + task: Ident, + args: String, + state: JobState, + subject: String, + submitter: Ident + ) extends Event { + val eventType = JobDone + val baseUrl = None + def account: AccountId = AccountId(group, submitter) + } + case object JobDone extends EventType { + def sample[F[_]: Sync](account: AccountId): F[JobDone] = + for { + id <- Ident.randomId[F] + ev = JobDone( + id, + account.collective, + Ident.unsafe("process-something-task"), + "", + JobState.running, + "Process 3 files", + account.user + ) + } yield ev + } + + def sample[F[_]: Sync]( + evt: EventType, + account: AccountId, + baseUrl: Option[LenientUri] + ): F[Event] = + evt match { + case TagsChanged => + TagsChanged.sample[F](account, baseUrl).map(x => x: Event) + case SetFieldValue => + SetFieldValue.sample[F](account, baseUrl).map(x => x: Event) + case ItemSelection => + ItemSelection.sample[F](account, baseUrl).map(x => x: Event) + case JobSubmitted => + JobSubmitted.sample[F](account).map(x => x: Event) + case JobDone => + JobDone.sample[F](account).map(x => x: Event) + case DeleteFieldValue => + DeleteFieldValue.sample[F](account, baseUrl).map(x => x: Event) + } +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/EventCodec.scala b/modules/notification/api/src/main/scala/docspell/notification/api/EventCodec.scala new file mode 100644 index 00000000..1b66841f --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/EventCodec.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import docspell.notification.api.Event._ + +import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder} +import io.circe.{Decoder, Encoder} + +trait EventCodec { + + implicit val tagsChangedDecoder: Decoder[TagsChanged] = deriveDecoder + implicit val tagsChangedEncoder: Encoder[TagsChanged] = deriveEncoder + + implicit val eventDecoder: Decoder[Event] = + deriveDecoder + implicit val eventEncoder: Encoder[Event] = + deriveEncoder +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/EventContext.scala b/modules/notification/api/src/main/scala/docspell/notification/api/EventContext.scala new file mode 100644 index 00000000..075d25eb --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/EventContext.scala @@ -0,0 +1,91 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.Applicative +import cats.Functor +import cats.data.Kleisli +import cats.data.OptionT + +import io.circe.Json +import io.circe.syntax._ + +trait EventContext { + + def event: Event + + def content: Json + + lazy val asJson: Json = + Json.obj( + "eventType" -> event.eventType.asJson, + "account" -> Json.obj( + "collective" -> event.account.collective.asJson, + "user" -> event.account.user.asJson, + "login" -> event.account.asJson + ), + "content" -> content + ) + + def defaultTitle: String + def defaultTitleHtml: String + + def defaultBody: String + def defaultBodyHtml: String + + def defaultBoth: String + def defaultBothHtml: String + + lazy val asJsonWithMessage: Json = { + val data = asJson + val msg = Json.obj( + "message" -> Json.obj( + "title" -> defaultTitle.asJson, + "body" -> defaultBody.asJson + ), + "messageHtml" -> Json.obj( + "title" -> defaultTitleHtml.asJson, + "body" -> defaultBodyHtml.asJson + ) + ) + + data.withObject(o1 => msg.withObject(o2 => o1.deepMerge(o2).asJson)) + } +} + +object EventContext { + def empty[F[_]](ev: Event): EventContext = + new EventContext { + val event = ev + def content = Json.obj() + def defaultTitle = "" + def defaultTitleHtml = "" + def defaultBody = "" + def defaultBodyHtml = "" + def defaultBoth: String = "" + def defaultBothHtml: String = "" + } + + /** For an event, the context can be created that is usually amended with more + * information. Since these information may be missing, it is possible that no context + * can be created. + */ + type Factory[F[_], E <: Event] = Kleisli[OptionT[F, *], E, EventContext] + + def factory[F[_]: Functor, E <: Event]( + run: E => F[EventContext] + ): Factory[F, E] = + Kleisli(run).mapK(OptionT.liftK[F]) + + def pure[F[_]: Applicative, E <: Event](run: E => EventContext): Factory[F, E] = + factory(ev => Applicative[F].pure(run(ev))) + + type Example[F[_], E <: Event] = Kleisli[F, E, EventContext] + + def example[F[_], E <: Event](run: E => F[EventContext]): Example[F, E] = + Kleisli(run) +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/EventExchange.scala b/modules/notification/api/src/main/scala/docspell/notification/api/EventExchange.scala new file mode 100644 index 00000000..6eb54387 --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/EventExchange.scala @@ -0,0 +1,54 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.Applicative +import cats.data.Kleisli +import cats.effect._ +import cats.effect.std.Queue +import cats.implicits._ +import fs2.Stream + +import docspell.common.Logger + +/** Combines a sink and reader to a place where events can be submitted and processed in a + * producer-consumer manner. + */ +trait EventExchange[F[_]] extends EventSink[F] with EventReader[F] {} + +object EventExchange { + private[this] val logger = org.log4s.getLogger + + def silent[F[_]: Applicative]: EventExchange[F] = + new EventExchange[F] { + def offer(event: Event): F[Unit] = + EventSink.silent[F].offer(event) + + def consume(maxConcurrent: Int)(run: Kleisli[F, Event, Unit]): Stream[F, Nothing] = + Stream.empty.covary[F] + } + + def circularQueue[F[_]: Async](queueSize: Int): F[EventExchange[F]] = + Queue.circularBuffer[F, Event](queueSize).map(q => new Impl(q)) + + final class Impl[F[_]: Async](queue: Queue[F, Event]) extends EventExchange[F] { + private[this] val log = Logger.log4s[F](logger) + + def offer(event: Event): F[Unit] = + log.debug(s"Pushing event to queue: $event") *> + queue.offer(event) + + private val logEvent: Kleisli[F, Event, Unit] = + Kleisli(ev => log.debug(s"Consuming event: $ev")) + + def consume(maxConcurrent: Int)(run: Kleisli[F, Event, Unit]): Stream[F, Nothing] = { + val stream = Stream.repeatEval(queue.take).evalMap((logEvent >> run).run) + log.s.info(s"Starting up $maxConcurrent notification event consumers").drain ++ + Stream(stream).repeat.take(maxConcurrent.toLong).parJoin(maxConcurrent).drain + } + } +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/EventReader.scala b/modules/notification/api/src/main/scala/docspell/notification/api/EventReader.scala new file mode 100644 index 00000000..9e8f44cd --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/EventReader.scala @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.data.Kleisli +import fs2.Stream + +trait EventReader[F[_]] { + + /** Stream to allow processing of events offered via a `EventSink` */ + def consume(maxConcurrent: Int)(run: Kleisli[F, Event, Unit]): Stream[F, Nothing] + +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/EventSink.scala b/modules/notification/api/src/main/scala/docspell/notification/api/EventSink.scala new file mode 100644 index 00000000..6973b8a8 --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/EventSink.scala @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.Applicative +import cats.implicits._ + +trait EventSink[F[_]] { + + /** Submit the event for asynchronous processing. */ + def offer(event: Event): F[Unit] +} + +object EventSink { + + def apply[F[_]](run: Event => F[Unit]): EventSink[F] = + (event: Event) => run(event) + + def silent[F[_]: Applicative]: EventSink[F] = + EventSink(_ => ().pure[F]) +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/NotificationBackend.scala b/modules/notification/api/src/main/scala/docspell/notification/api/NotificationBackend.scala new file mode 100644 index 00000000..c543b806 --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/NotificationBackend.scala @@ -0,0 +1,89 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.Applicative +import cats.data.NonEmptyList +import cats.effect._ +import cats.implicits._ +import cats.kernel.Monoid +import fs2.Stream + +import docspell.common._ + +/** Pushes notification messages/events to an external system */ +trait NotificationBackend[F[_]] { + + def send(event: EventContext): F[Unit] + +} + +object NotificationBackend { + + def apply[F[_]](run: EventContext => F[Unit]): NotificationBackend[F] = + (event: EventContext) => run(event) + + def silent[F[_]: Applicative]: NotificationBackend[F] = + NotificationBackend(_ => ().pure[F]) + + def combine[F[_]: Concurrent]( + ba: NotificationBackend[F], + bb: NotificationBackend[F] + ): NotificationBackend[F] = + (ba, bb) match { + case (a: Combined[F], b: Combined[F]) => + Combined(a.delegates.concatNel(b.delegates)) + case (a: Combined[F], _) => + Combined(bb :: a.delegates) + case (_, b: Combined[F]) => + Combined(ba :: b.delegates) + case (_, _) => + Combined(NonEmptyList.of(ba, bb)) + } + + def ignoreErrors[F[_]: Sync]( + logger: Logger[F] + )(nb: NotificationBackend[F]): NotificationBackend[F] = + NotificationBackend { event => + nb.send(event).attempt.flatMap { + case Right(_) => + logger.debug(s"Successfully sent notification: $event") + case Left(ex) => + logger.error(ex)(s"Error sending notification: $event") + } + } + + final private case class Combined[F[_]: Concurrent]( + delegates: NonEmptyList[NotificationBackend[F]] + ) extends NotificationBackend[F] { + val parNum = math.max(2, Runtime.getRuntime.availableProcessors() * 2) + + def send(event: EventContext): F[Unit] = + Stream + .emits(delegates.toList) + .covary[F] + .parEvalMapUnordered(math.min(delegates.size, parNum))(_.send(event)) + .drain + .compile + .drain + } + + def combineAll[F[_]: Concurrent]( + bes: NonEmptyList[NotificationBackend[F]] + ): NotificationBackend[F] = + bes.tail match { + case Nil => bes.head + case next :: Nil => + Combined(NonEmptyList.of(bes.head, next)) + case next :: more => + val first: NotificationBackend[F] = Combined(NonEmptyList.of(bes.head, next)) + more.foldLeft(first)(combine) + } + + implicit def monoid[F[_]: Concurrent]: Monoid[NotificationBackend[F]] = + Monoid.instance(silent[F], combine[F]) +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/NotificationChannel.scala b/modules/notification/api/src/main/scala/docspell/notification/api/NotificationChannel.scala new file mode 100644 index 00000000..5a8d05e2 --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/NotificationChannel.scala @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.data.NonEmptyList + +import docspell.common._ + +import emil._ + +sealed trait NotificationChannel { self: Product => + def name: String = + productPrefix.toLowerCase +} + +object NotificationChannel { + + final case class Email( + config: MailConfig, + from: MailAddress, + recipients: NonEmptyList[MailAddress] + ) extends NotificationChannel + + final case class HttpPost( + url: LenientUri, + headers: Map[String, String] + ) extends NotificationChannel + + final case class Gotify(url: LenientUri, appKey: Password) extends NotificationChannel + + final case class Matrix( + homeServer: LenientUri, + roomId: String, + accessToken: Password, + messageType: String + ) extends NotificationChannel +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/NotificationModule.scala b/modules/notification/api/src/main/scala/docspell/notification/api/NotificationModule.scala new file mode 100644 index 00000000..a87e819d --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/NotificationModule.scala @@ -0,0 +1,62 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import cats.Applicative +import cats.data.{Kleisli, OptionT} +import cats.implicits._ +import fs2.Stream + +import docspell.common.Logger + +trait NotificationModule[F[_]] + extends EventSink[F] + with EventReader[F] + with EventExchange[F] { + + /** Sends an event as notification through configured channels. */ + def notifyEvent: Kleisli[F, Event, Unit] + + /** Send the event data via the given channels. */ + def send( + logger: Logger[F], + event: EventContext, + channels: Seq[NotificationChannel] + ): F[Unit] + + /** Amend an event with additional data. */ + def eventContext: EventContext.Factory[F, Event] + + /** Create an example event context. */ + def sampleEvent: EventContext.Example[F, Event] + + /** Consume all offered events asynchronously. */ + def consumeAllEvents(maxConcurrent: Int): Stream[F, Nothing] = + consume(maxConcurrent)(notifyEvent) +} + +object NotificationModule { + + def noop[F[_]: Applicative]: NotificationModule[F] = + new NotificationModule[F] { + val noSend = NotificationBackend.silent[F] + val noExchange = EventExchange.silent[F] + + def notifyEvent = Kleisli(_ => ().pure[F]) + def eventContext = Kleisli(_ => OptionT.none[F, EventContext]) + def sampleEvent = EventContext.example(ev => EventContext.empty(ev).pure[F]) + def send( + logger: Logger[F], + event: EventContext, + channels: Seq[NotificationChannel] + ) = + noSend.send(event) + def offer(event: Event) = noExchange.offer(event) + def consume(maxConcurrent: Int)(run: Kleisli[F, Event, Unit]) = + noExchange.consume(maxConcurrent)(run) + } +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/PeriodicDueItemsArgs.scala b/modules/notification/api/src/main/scala/docspell/notification/api/PeriodicDueItemsArgs.scala new file mode 100644 index 00000000..2a34ec26 --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/PeriodicDueItemsArgs.scala @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import docspell.common._ + +import emil.MailAddress +import io.circe.generic.semiauto +import io.circe.{Decoder, Encoder} + +final case class PeriodicDueItemsArgs( + account: AccountId, + channel: ChannelOrRef, + remindDays: Int, + daysBack: Option[Int], + tagsInclude: List[Ident], + tagsExclude: List[Ident], + baseUrl: Option[LenientUri] +) + +object PeriodicDueItemsArgs { + val taskName = Ident.unsafe("periodic-due-items-notify") + + implicit def jsonDecoder(implicit + mc: Decoder[MailAddress] + ): Decoder[PeriodicDueItemsArgs] = { + implicit val x = ChannelOrRef.jsonDecoder + semiauto.deriveDecoder + } + + implicit def jsonEncoder(implicit + mc: Encoder[MailAddress] + ): Encoder[PeriodicDueItemsArgs] = { + implicit val x = ChannelOrRef.jsonEncoder + semiauto.deriveEncoder + } +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/PeriodicQueryArgs.scala b/modules/notification/api/src/main/scala/docspell/notification/api/PeriodicQueryArgs.scala new file mode 100644 index 00000000..3f79bf90 --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/PeriodicQueryArgs.scala @@ -0,0 +1,38 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.api + +import docspell.common._ + +import emil.MailAddress +import io.circe.generic.semiauto +import io.circe.{Decoder, Encoder} + +final case class PeriodicQueryArgs( + account: AccountId, + channel: ChannelOrRef, + query: ItemQueryString, + baseUrl: Option[LenientUri] +) + +object PeriodicQueryArgs { + val taskName = Ident.unsafe("periodic-query-notify") + + implicit def jsonDecoder(implicit + mc: Decoder[MailAddress] + ): Decoder[PeriodicQueryArgs] = { + implicit val x = ChannelOrRef.jsonDecoder + semiauto.deriveDecoder + } + + implicit def jsonEncoder(implicit + mc: Encoder[MailAddress] + ): Encoder[PeriodicQueryArgs] = { + implicit val x = ChannelOrRef.jsonEncoder + semiauto.deriveEncoder + } +} diff --git a/modules/notification/api/src/main/scala/docspell/notification/api/package.scala b/modules/notification/api/src/main/scala/docspell/notification/api/package.scala new file mode 100644 index 00000000..74f2e41e --- /dev/null +++ b/modules/notification/api/src/main/scala/docspell/notification/api/package.scala @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification + +import emil.MailAddress +import io.circe.{Decoder, Encoder} + +package object api { + + type ChannelOrRef = Either[ChannelRef, Channel] + + object ChannelOrRef { + implicit def jsonDecoder(implicit mc: Decoder[MailAddress]): Decoder[ChannelOrRef] = + Channel.jsonDecoder.either(ChannelRef.jsonDecoder).map(_.swap) + + implicit def jsonEncoder(implicit mc: Encoder[MailAddress]): Encoder[ChannelOrRef] = + Encoder.instance(_.fold(ChannelRef.jsonEncoder.apply, Channel.jsonEncoder.apply)) + + implicit class ChannelOrRefOpts(cr: ChannelOrRef) { + def channelType: ChannelType = + cr.fold(_.channelType, _.channelType) + } + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/AbstractEventContext.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/AbstractEventContext.scala new file mode 100644 index 00000000..0d42e43c --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/AbstractEventContext.scala @@ -0,0 +1,63 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import docspell.notification.api.EventContext + +import yamusca.circe._ +import yamusca.implicits._ +import yamusca.imports._ + +abstract class AbstractEventContext extends EventContext { + + def titleTemplate: Template + + def bodyTemplate: Template + + def render(template: Template): String = + asJson.render(template).trim() + + def renderHtml(template: Template): String = + Markdown.toHtml(render(template)) + + lazy val defaultTitle: String = + render(titleTemplate) + + lazy val defaultTitleHtml: String = + renderHtml(titleTemplate) + + lazy val defaultBody: String = + render(bodyTemplate) + + lazy val defaultBodyHtml: String = + renderHtml(bodyTemplate) + + lazy val defaultBoth: String = + render( + AbstractEventContext.concat( + titleTemplate, + AbstractEventContext.sepTemplate, + bodyTemplate + ) + ) + + lazy val defaultBothHtml: String = + renderHtml( + AbstractEventContext.concat( + titleTemplate, + AbstractEventContext.sepTemplate, + bodyTemplate + ) + ) +} + +object AbstractEventContext { + private val sepTemplate: Template = mustache": " + + private def concat(t1: Template, ts: Template*): Template = + Template(ts.foldLeft(t1.els)((res, el) => res ++ el.els)) +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/DbEventContext.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/DbEventContext.scala new file mode 100644 index 00000000..c16d1435 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/DbEventContext.scala @@ -0,0 +1,41 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.data.Kleisli + +import docspell.notification.api.{Event, EventContext} +import docspell.notification.impl.context._ + +import doobie._ + +object DbEventContext { + + type Factory = EventContext.Factory[ConnectionIO, Event] + + def apply: Factory = + Kleisli { + case ev: Event.TagsChanged => + TagsChangedCtx.apply.run(ev) + + case ev: Event.SetFieldValue => + SetFieldValueCtx.apply.run(ev) + + case ev: Event.DeleteFieldValue => + DeleteFieldValueCtx.apply.run(ev) + + case ev: Event.ItemSelection => + ItemSelectionCtx.apply.run(ev) + + case ev: Event.JobSubmitted => + JobSubmittedCtx.apply.run(ev) + + case ev: Event.JobDone => + JobDoneCtx.apply.run(ev) + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/EmailBackend.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/EmailBackend.scala new file mode 100644 index 00000000..f93202c8 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/EmailBackend.scala @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.effect._ +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api._ + +import emil.Emil +import emil.markdown.MarkdownBody + +final class EmailBackend[F[_]: Sync]( + channel: NotificationChannel.Email, + mailService: Emil[F], + logger: Logger[F] +) extends NotificationBackend[F] { + + import emil.builder._ + + def send(event: EventContext): F[Unit] = { + val mail = + MailBuilder.build( + From(channel.from), + Tos(channel.recipients.toList), + Subject(event.defaultTitle), + MarkdownBody[F](event.defaultBody) + ) + + logger.debug(s"Attempting to send notification mail: $channel") *> + mailService(channel.config) + .send(mail) + .flatMap(msgId => logger.info(s"Send notification mail ${msgId.head}")) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/EventNotify.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/EventNotify.scala new file mode 100644 index 00000000..1b7e95a2 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/EventNotify.scala @@ -0,0 +1,52 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.data.Kleisli +import cats.data.OptionT +import cats.effect._ + +import docspell.common.Logger +import docspell.notification.api.Event +import docspell.notification.api.NotificationBackend +import docspell.store.Store +import docspell.store.queries.QNotification + +import emil.Emil +import org.http4s.client.Client + +/** Represents the actual work done for each event. */ +object EventNotify { + private[this] val log4sLogger = org.log4s.getLogger + + def apply[F[_]: Async]( + store: Store[F], + mailService: Emil[F], + client: Client[F] + ): Kleisli[F, Event, Unit] = + Kleisli { event => + (for { + hooks <- OptionT.liftF(store.transact(QNotification.findChannelsForEvent(event))) + evctx <- DbEventContext.apply.run(event).mapK(store.transform) + channels = hooks + .filter(hc => + hc.channels.nonEmpty && hc.hook.eventFilter.forall(_.matches(evctx.asJson)) + ) + .flatMap(_.channels) + backend = + if (channels.isEmpty) NotificationBackend.silent[F] + else + NotificationBackendImpl.forChannelsIgnoreErrors( + client, + mailService, + Logger.log4s(log4sLogger) + )(channels) + _ <- OptionT.liftF(backend.send(evctx)) + } yield ()).getOrElse(()) + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/ExampleEventContext.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/ExampleEventContext.scala new file mode 100644 index 00000000..8bcae7cd --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/ExampleEventContext.scala @@ -0,0 +1,39 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.data.Kleisli +import cats.effect.kernel.Sync + +import docspell.notification.api.{Event, EventContext} +import docspell.notification.impl.context._ + +object ExampleEventContext { + + type Factory[F[_]] = EventContext.Example[F, Event] + + def apply[F[_]: Sync]: Factory[F] = + Kleisli { + case ev: Event.TagsChanged => + TagsChangedCtx.sample.run(ev) + + case ev: Event.SetFieldValue => + SetFieldValueCtx.sample.run(ev) + + case ev: Event.DeleteFieldValue => + DeleteFieldValueCtx.sample.run(ev) + + case ev: Event.ItemSelection => + ItemSelectionCtx.sample.run(ev) + + case ev: Event.JobSubmitted => + JobSubmittedCtx.sample.run(ev) + + case ev: Event.JobDone => + JobDoneCtx.sample.run(ev) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/GotifyBackend.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/GotifyBackend.scala new file mode 100644 index 00000000..2d955a8a --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/GotifyBackend.scala @@ -0,0 +1,49 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.effect._ +import cats.implicits._ + +import docspell.common.Logger +import docspell.notification.api._ + +import io.circe.Json +import org.http4s.Uri +import org.http4s.circe.CirceEntityCodec._ +import org.http4s.client.Client +import org.http4s.client.dsl.Http4sClientDsl +import org.http4s.dsl.Http4sDsl + +final class GotifyBackend[F[_]: Async]( + channel: NotificationChannel.Gotify, + client: Client[F], + logger: Logger[F] +) extends NotificationBackend[F] { + + val dsl = new Http4sDsl[F] with Http4sClientDsl[F] {} + import dsl._ + + def send(event: EventContext): F[Unit] = { + val url = Uri.unsafeFromString((channel.url / "message").asString) + val req = POST( + Json.obj( + "title" -> Json.fromString(event.defaultTitle), + "message" -> Json.fromString(event.defaultBody), + "extras" -> Json.obj( + "client::display" -> Json.obj( + "contentType" -> Json.fromString("text/markdown") + ) + ) + ), + url + ) + .putHeaders("X-Gotify-Key" -> channel.appKey.pass) + logger.debug(s"Seding request: $req") *> + HttpSend.sendRequest(client, req, channel, logger) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/HttpPostBackend.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/HttpPostBackend.scala new file mode 100644 index 00000000..226f5522 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/HttpPostBackend.scala @@ -0,0 +1,36 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.effect._ +import cats.implicits._ + +import docspell.common.Logger +import docspell.notification.api._ + +import org.http4s.Uri +import org.http4s.client.Client +import org.http4s.client.dsl.Http4sClientDsl +import org.http4s.dsl.Http4sDsl + +final class HttpPostBackend[F[_]: Async]( + channel: NotificationChannel.HttpPost, + client: Client[F], + logger: Logger[F] +) extends NotificationBackend[F] { + + val dsl = new Http4sDsl[F] with Http4sClientDsl[F] {} + import dsl._ + import org.http4s.circe.CirceEntityCodec._ + + def send(event: EventContext): F[Unit] = { + val url = Uri.unsafeFromString(channel.url.asString) + val req = POST(event.asJsonWithMessage, url).putHeaders(channel.headers.toList) + logger.debug(s"$channel sending request: $req") *> + HttpSend.sendRequest(client, req, channel, logger) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/HttpSend.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/HttpSend.scala new file mode 100644 index 00000000..38fcd520 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/HttpSend.scala @@ -0,0 +1,35 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.effect._ +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api.NotificationChannel + +import org.http4s.Request +import org.http4s.client.Client + +object HttpSend { + + def sendRequest[F[_]: Async]( + client: Client[F], + req: Request[F], + channel: NotificationChannel, + logger: Logger[F] + ) = + client + .status(req) + .flatMap { status => + if (status.isSuccess) logger.info(s"Send notification via $channel") + else + Async[F].raiseError[Unit]( + new Exception(s"Error sending notification via $channel: $status") + ) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/Markdown.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/Markdown.scala new file mode 100644 index 00000000..aecf789b --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/Markdown.scala @@ -0,0 +1,40 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import java.util + +import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension +import com.vladsch.flexmark.ext.tables.TablesExtension +import com.vladsch.flexmark.html.HtmlRenderer +import com.vladsch.flexmark.parser.Parser +import com.vladsch.flexmark.util.data.{DataKey, MutableDataSet} + +object Markdown { + + def toHtml(md: String): String = { + val p = createParser() + val r = createRenderer() + val doc = p.parse(md) + r.render(doc).trim + } + + private def createParser(): Parser = { + val opts = new MutableDataSet() + opts.set( + Parser.EXTENSIONS.asInstanceOf[DataKey[util.Collection[_]]], + util.Arrays.asList(TablesExtension.create(), StrikethroughExtension.create()) + ); + + Parser.builder(opts).build() + } + + private def createRenderer(): HtmlRenderer = { + val opts = new MutableDataSet() + HtmlRenderer.builder(opts).build() + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/MatrixBackend.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/MatrixBackend.scala new file mode 100644 index 00000000..4222b004 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/MatrixBackend.scala @@ -0,0 +1,45 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.effect._ + +import docspell.common.Logger +import docspell.notification.api._ + +import org.http4s.Uri +import org.http4s.client.Client +import org.http4s.client.dsl.Http4sClientDsl +import org.http4s.dsl.Http4sDsl + +final class MatrixBackend[F[_]: Async]( + channel: NotificationChannel.Matrix, + client: Client[F], + logger: Logger[F] +) extends NotificationBackend[F] { + + val dsl = new Http4sDsl[F] with Http4sClientDsl[F] {} + import dsl._ + import org.http4s.circe.CirceEntityCodec._ + + def send(event: EventContext): F[Unit] = { + val url = + (channel.homeServer / "_matrix" / "client" / "r0" / "rooms" / channel.roomId / "send" / "m.room.message") + .withQuery("access_token", channel.accessToken.pass) + val uri = Uri.unsafeFromString(url.asString) + val req = POST( + Map( + "msgtype" -> channel.messageType, + "format" -> "org.matrix.custom.html", + "formatted_body" -> event.defaultBothHtml, + "body" -> event.defaultBoth + ), + uri + ) + HttpSend.sendRequest(client, req, channel, logger) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationBackendImpl.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationBackendImpl.scala new file mode 100644 index 00000000..48a3406c --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationBackendImpl.scala @@ -0,0 +1,61 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.data.NonEmptyList +import cats.effect._ + +import docspell.common.Logger +import docspell.notification.api.NotificationBackend.{combineAll, ignoreErrors, silent} +import docspell.notification.api.{NotificationBackend, NotificationChannel} + +import emil.Emil +import org.http4s.client.Client + +object NotificationBackendImpl { + + def forChannel[F[_]: Async](client: Client[F], mailService: Emil[F], logger: Logger[F])( + channel: NotificationChannel + ): NotificationBackend[F] = + channel match { + case c: NotificationChannel.Email => + new EmailBackend[F](c, mailService, logger) + case c: NotificationChannel.HttpPost => + new HttpPostBackend[F](c, client, logger) + case c: NotificationChannel.Gotify => + new GotifyBackend[F](c, client, logger) + case c: NotificationChannel.Matrix => + new MatrixBackend[F](c, client, logger) + } + + def forChannels[F[_]: Async](client: Client[F], maiService: Emil[F], logger: Logger[F])( + channels: Seq[NotificationChannel] + ): NotificationBackend[F] = + NonEmptyList.fromFoldable(channels) match { + case Some(nel) => + combineAll[F](nel.map(forChannel(client, maiService, logger))) + case None => + silent[F] + } + + def forChannelsIgnoreErrors[F[_]: Async]( + client: Client[F], + mailService: Emil[F], + logger: Logger[F] + )( + channels: Seq[NotificationChannel] + ): NotificationBackend[F] = + NonEmptyList.fromFoldable(channels) match { + case Some(nel) => + combineAll( + nel.map(forChannel[F](client, mailService, logger)).map(ignoreErrors[F](logger)) + ) + case None => + silent[F] + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationModuleImpl.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationModuleImpl.scala new file mode 100644 index 00000000..9c49e9da --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/NotificationModuleImpl.scala @@ -0,0 +1,51 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl + +import cats.data.Kleisli +import cats.effect.kernel.Async +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api._ +import docspell.store.Store + +import emil.Emil +import org.http4s.client.Client + +object NotificationModuleImpl { + + def apply[F[_]: Async]( + store: Store[F], + mailService: Emil[F], + client: Client[F], + queueSize: Int + ): F[NotificationModule[F]] = + for { + exchange <- EventExchange.circularQueue[F](queueSize) + } yield new NotificationModule[F] { + val notifyEvent = EventNotify(store, mailService, client) + + val eventContext = DbEventContext.apply.mapF(_.mapK(store.transform)) + + val sampleEvent = ExampleEventContext.apply + + def send( + logger: Logger[F], + event: EventContext, + channels: Seq[NotificationChannel] + ) = + NotificationBackendImpl + .forChannels(client, mailService, logger)(channels) + .send(event) + + def offer(event: Event) = exchange.offer(event) + + def consume(maxConcurrent: Int)(run: Kleisli[F, Event, Unit]) = + exchange.consume(maxConcurrent)(run) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/BasicData.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/BasicData.scala new file mode 100644 index 00000000..3bfac103 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/BasicData.scala @@ -0,0 +1,149 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.data.NonEmptyList +import cats.effect.Sync +import cats.implicits._ + +import docspell.common._ +import docspell.query.ItemQuery +import docspell.query.ItemQueryDsl +import docspell.store.qb.Batch +import docspell.store.queries.ListItem +import docspell.store.queries.QItem +import docspell.store.queries.Query +import docspell.store.records._ + +import doobie._ +import io.circe.Encoder +import io.circe.generic.semiauto.deriveEncoder + +object BasicData { + + final case class Tag(id: Ident, name: String, category: Option[String]) + object Tag { + implicit val jsonEncoder: Encoder[Tag] = deriveEncoder + + def apply(t: RTag): Tag = Tag(t.tagId, t.name, t.category) + + def sample[F[_]: Sync](id: String): F[Tag] = + Sync[F] + .delay(if (math.random() > 0.5) "Invoice" else "Receipt") + .map(tag => Tag(Ident.unsafe(id), tag, Some("doctype"))) + } + + final case class Item( + id: Ident, + name: String, + dateMillis: Timestamp, + date: String, + direction: Direction, + state: ItemState, + dueDateMillis: Option[Timestamp], + dueDate: Option[String], + source: String, + overDue: Boolean, + dueIn: Option[String], + corrOrg: Option[String], + notes: Option[String] + ) + + object Item { + implicit val jsonEncoder: Encoder[Item] = deriveEncoder + + private def calcDueLabels(now: Timestamp, dueDate: Option[Timestamp]) = { + val dueIn = dueDate.map(dt => Timestamp.daysBetween(now, dt)) + val dueInLabel = dueIn.map { + case 0 => "**today**" + case 1 => "**tomorrow**" + case -1 => s"**yesterday**" + case n if n > 0 => s"in $n days" + case n => s"${n * -1} days ago" + } + (dueIn, dueInLabel) + } + + def find( + itemIds: NonEmptyList[Ident], + account: AccountId, + now: Timestamp + ): ConnectionIO[Vector[Item]] = { + import ItemQueryDsl._ + + val q = Query( + Query.Fix( + account, + Some(ItemQuery.Attr.ItemId.in(itemIds.map(_.id))), + Some(_.created) + ) + ) + for { + items <- QItem + .findItems(q, now.toUtcDate, 25, Batch.limit(itemIds.size)) + .compile + .to(Vector) + } yield items.map(apply(now)) + } + + def apply(now: Timestamp)(i: ListItem): Item = { + val (dueIn, dueInLabel) = calcDueLabels(now, i.dueDate) + Item( + i.id, + i.name, + i.date, + i.date.toUtcDate.toString, + i.direction, + i.state, + i.dueDate, + i.dueDate.map(_.toUtcDate.toString), + i.source, + dueIn.exists(_ < 0), + dueInLabel, + i.corrOrg.map(_.name), + i.notes + ) + } + + def sample[F[_]: Sync](id: Ident): F[Item] = + Timestamp.current[F].map { now => + val dueDate = if (id.hashCode % 2 == 0) Some(now + Duration.days(3)) else None + val (dueIn, dueInLabel) = calcDueLabels(now, dueDate) + Item( + id, + "MapleSirupLtd_202331.pdf", + now - Duration.days(62), + (now - Duration.days(62)).toUtcDate.toString, + Direction.Incoming, + ItemState.Confirmed, + dueDate, + dueDate.map(_.toUtcDate.toString), + "webapp", + dueIn.exists(_ < 0), + dueInLabel, + Some("Acme AG"), + None + ) + } + } + + final case class Field( + id: Ident, + name: Ident, + label: Option[String], + ftype: CustomFieldType + ) + object Field { + implicit val jsonEncoder: Encoder[Field] = deriveEncoder + + def apply(r: RCustomField): Field = + Field(r.id, r.name, r.label, r.ftype) + + def sample[F[_]: Sync](id: Ident): F[Field] = + Sync[F].delay(Field(id, Ident.unsafe("chf"), Some("CHF"), CustomFieldType.Money)) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/DeleteFieldValueCtx.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/DeleteFieldValueCtx.scala new file mode 100644 index 00000000..cbee4f07 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/DeleteFieldValueCtx.scala @@ -0,0 +1,83 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.data.Kleisli +import cats.data.OptionT +import cats.effect.Sync +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api.{Event, EventContext} +import docspell.notification.impl.AbstractEventContext +import docspell.notification.impl.context.BasicData._ +import docspell.notification.impl.context.Syntax._ +import docspell.store.records._ + +import doobie._ +import io.circe.Encoder +import io.circe.syntax._ +import yamusca.implicits._ + +final case class DeleteFieldValueCtx( + event: Event.DeleteFieldValue, + data: DeleteFieldValueCtx.Data +) extends AbstractEventContext { + + val content = data.asJson + + val titleTemplate = mustache"{{eventType}} (by *{{account.user}}*)" + val bodyTemplate = + mustache"""{{#content}}{{#field.label}}*{{field.label}}* {{/field.label}}{{^field.label}}*{{field.name}}* {{/field.label}} was removed from {{#items}}{{^-first}}, {{/-first}}{{#itemUrl}}[`{{name}}`]({{{itemUrl}}}/{{{id}}}){{/itemUrl}}{{^itemUrl}}`{{name}}`{{/itemUrl}}{{/items}}.{{/content}}""" + +} + +object DeleteFieldValueCtx { + type Factory = EventContext.Factory[ConnectionIO, Event.DeleteFieldValue] + + def apply: Factory = + Kleisli(ev => + for { + now <- OptionT.liftF(Timestamp.current[ConnectionIO]) + items <- OptionT.liftF(Item.find(ev.items, ev.account, now)) + field <- OptionT(RCustomField.findById(ev.field, ev.account.collective)) + msg = DeleteFieldValueCtx( + ev, + Data( + ev.account, + items.toList, + Field(field), + ev.itemUrl + ) + ) + } yield msg + ) + + def sample[F[_]: Sync]: EventContext.Example[F, Event.DeleteFieldValue] = + EventContext.example(ev => + for { + items <- ev.items.traverse(Item.sample[F]) + field <- Field.sample[F](ev.field) + } yield DeleteFieldValueCtx( + ev, + Data(ev.account, items.toList, field, ev.itemUrl) + ) + ) + + final case class Data( + account: AccountId, + items: List[Item], + field: Field, + itemUrl: Option[String] + ) + + object Data { + implicit val jsonEncoder: Encoder[Data] = + io.circe.generic.semiauto.deriveEncoder + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/ItemSelectionCtx.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/ItemSelectionCtx.scala new file mode 100644 index 00000000..9c3a700d --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/ItemSelectionCtx.scala @@ -0,0 +1,117 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.effect._ +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api._ +import docspell.notification.impl.AbstractEventContext +import docspell.notification.impl.context.Syntax._ +import docspell.store.queries.ListItem + +import doobie._ +import io.circe.Encoder +import io.circe.syntax._ +import yamusca.implicits._ + +final case class ItemSelectionCtx(event: Event.ItemSelection, data: ItemSelectionCtx.Data) + extends AbstractEventContext { + + val content = data.asJson + + val titleTemplate = mustache"Your items" + val bodyTemplate = mustache""" +Hello {{{ content.username }}}, + +this is Docspell informing you about your next items. + +{{#content}} +{{#itemUrl}} +{{#items}} +- {{#overDue}}**(OVERDUE)** {{/overDue}}[{{name}}]({{itemUrl}}/{{id}}){{#dueDate}}, {{#overDue}}was {{/overDue}}due {{dueIn}} on *{{dueDate}}*{{/dueDate}}; {{#corrOrg}}from {{corrOrg}}{{/corrOrg}} received on {{date}} via {{source}} +{{/items}} +{{/itemUrl}} +{{^itemUrl}} +{{#items}} +- {{#overDue}}**(OVERDUE)** {{/overDue}}*{{name}}*{{#dueDate}}, {{#overDue}}was {{/overDue}}due {{dueIn}} on *{{dueDate}}*{{/dueDate}}; {{#corrOrg}}from {{corrOrg}}{{/corrOrg}} received on {{date}} via {{source}} +{{/items}} +{{/itemUrl}} +{{#more}} +- … more have been left out for brevity +{{/more}} +{{/content}} + + +Sincerely yours, + +Docspell +""" +} + +object ItemSelectionCtx { + import BasicData._ + + type Factory = EventContext.Factory[ConnectionIO, Event.ItemSelection] + + def apply: Factory = + EventContext.factory(ev => + for { + now <- Timestamp.current[ConnectionIO] + items <- Item.find(ev.items, ev.account, now) + msg = ItemSelectionCtx( + ev, + Data( + ev.account, + items.toList, + ev.itemUrl, + ev.more, + ev.account.user.id + ) + ) + } yield msg + ) + + def sample[F[_]: Sync]: EventContext.Example[F, Event.ItemSelection] = + EventContext.example(ev => + for { + items <- ev.items.traverse(Item.sample[F]) + } yield ItemSelectionCtx( + ev, + Data(ev.account, items.toList, ev.itemUrl, ev.more, ev.account.user.id) + ) + ) + + final case class Data( + account: AccountId, + items: List[Item], + itemUrl: Option[String], + more: Boolean, + username: String + ) + object Data { + implicit val jsonEncoder: Encoder[Data] = + io.circe.generic.semiauto.deriveEncoder + + def create( + account: AccountId, + items: Vector[ListItem], + baseUrl: Option[LenientUri], + more: Boolean, + now: Timestamp + ): Data = + Data( + account, + items.map(Item(now)).toList, + baseUrl.map(_.asString), + more, + account.user.id + ) + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobDoneCtx.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobDoneCtx.scala new file mode 100644 index 00000000..48009186 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobDoneCtx.scala @@ -0,0 +1,56 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.effect._ + +import docspell.common._ +import docspell.notification.api._ +import docspell.notification.impl.AbstractEventContext + +import doobie._ +import io.circe.Encoder +import io.circe.syntax._ +import yamusca.implicits._ + +final case class JobDoneCtx(event: Event.JobDone, data: JobDoneCtx.Data) + extends AbstractEventContext { + + val content = data.asJson + + val titleTemplate = mustache"{{eventType}} (by *{{account.user}}*)" + val bodyTemplate = mustache"""{{#content}}_'{{subject}}'_ finished {{/content}}""" +} + +object JobDoneCtx { + + type Factory = EventContext.Factory[ConnectionIO, Event.JobDone] + + def apply: Factory = + EventContext.pure(ev => JobDoneCtx(ev, Data(ev))) + + def sample[F[_]: Sync]: EventContext.Example[F, Event.JobDone] = + EventContext.example(ev => Sync[F].pure(JobDoneCtx(ev, Data(ev)))) + + final case class Data( + job: Ident, + group: Ident, + task: Ident, + args: String, + state: JobState, + subject: String, + submitter: Ident + ) + object Data { + implicit val jsonEncoder: Encoder[Data] = + io.circe.generic.semiauto.deriveEncoder + + def apply(ev: Event.JobDone): Data = + Data(ev.jobId, ev.group, ev.task, ev.args, ev.state, ev.subject, ev.submitter) + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobSubmittedCtx.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobSubmittedCtx.scala new file mode 100644 index 00000000..3fb0bf62 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/JobSubmittedCtx.scala @@ -0,0 +1,57 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.effect._ + +import docspell.common._ +import docspell.notification.api._ +import docspell.notification.impl.AbstractEventContext + +import doobie._ +import io.circe.Encoder +import io.circe.syntax._ +import yamusca.implicits._ + +final case class JobSubmittedCtx(event: Event.JobSubmitted, data: JobSubmittedCtx.Data) + extends AbstractEventContext { + + val content = data.asJson + + val titleTemplate = mustache"{{eventType}} (by *{{account.user}}*)" + val bodyTemplate = + mustache"""{{#content}}_'{{subject}}'_ submitted by {{submitter}} {{/content}}""" +} + +object JobSubmittedCtx { + + type Factory = EventContext.Factory[ConnectionIO, Event.JobSubmitted] + + def apply: Factory = + EventContext.pure(ev => JobSubmittedCtx(ev, Data(ev))) + + def sample[F[_]: Sync]: EventContext.Example[F, Event.JobSubmitted] = + EventContext.example(ev => Sync[F].pure(JobSubmittedCtx(ev, Data(ev)))) + + final case class Data( + job: Ident, + group: Ident, + task: Ident, + args: String, + state: JobState, + subject: String, + submitter: Ident + ) + object Data { + implicit val jsonEncoder: Encoder[Data] = + io.circe.generic.semiauto.deriveEncoder + + def apply(ev: Event.JobSubmitted): Data = + Data(ev.jobId, ev.group, ev.task, ev.args, ev.state, ev.subject, ev.submitter) + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/SetFieldValueCtx.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/SetFieldValueCtx.scala new file mode 100644 index 00000000..fd67c714 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/SetFieldValueCtx.scala @@ -0,0 +1,83 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.data.Kleisli +import cats.data.OptionT +import cats.effect.Sync +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api.{Event, EventContext} +import docspell.notification.impl.AbstractEventContext +import docspell.notification.impl.context.BasicData._ +import docspell.notification.impl.context.Syntax._ +import docspell.store.records._ + +import doobie._ +import io.circe.Encoder +import io.circe.syntax._ +import yamusca.implicits._ + +final case class SetFieldValueCtx(event: Event.SetFieldValue, data: SetFieldValueCtx.Data) + extends AbstractEventContext { + + val content = data.asJson + + val titleTemplate = mustache"{{eventType}} (by *{{account.user}}*)" + val bodyTemplate = + mustache"""{{#content}}{{#field.label}}*{{field.label}}* {{/field.label}}{{^field.label}}*{{field.name}}* {{/field.label}} was set to '{{value}}' on {{#items}}{{^-first}}, {{/-first}}{{#itemUrl}}[`{{name}}`]({{{itemUrl}}}/{{{id}}}){{/itemUrl}}{{^itemUrl}}`{{name}}`{{/itemUrl}}{{/items}}.{{/content}}""" + +} + +object SetFieldValueCtx { + type Factory = EventContext.Factory[ConnectionIO, Event.SetFieldValue] + + def apply: Factory = + Kleisli(ev => + for { + now <- OptionT.liftF(Timestamp.current[ConnectionIO]) + items <- OptionT.liftF(Item.find(ev.items, ev.account, now)) + field <- OptionT(RCustomField.findById(ev.field, ev.account.collective)) + msg = SetFieldValueCtx( + ev, + Data( + ev.account, + items.toList, + Field(field), + ev.value, + ev.itemUrl + ) + ) + } yield msg + ) + + def sample[F[_]: Sync]: EventContext.Example[F, Event.SetFieldValue] = + EventContext.example(ev => + for { + items <- ev.items.traverse(Item.sample[F]) + field <- Field.sample[F](ev.field) + } yield SetFieldValueCtx( + ev, + Data(ev.account, items.toList, field, ev.value, ev.itemUrl) + ) + ) + + final case class Data( + account: AccountId, + items: List[Item], + field: Field, + value: String, + itemUrl: Option[String] + ) + + object Data { + implicit val jsonEncoder: Encoder[Data] = + io.circe.generic.semiauto.deriveEncoder + } + +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/Syntax.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/Syntax.scala new file mode 100644 index 00000000..74bec6b8 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/Syntax.scala @@ -0,0 +1,18 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import docspell.notification.api.Event + +object Syntax { + + implicit final class EventOps(ev: Event) { + + def itemUrl: Option[String] = + ev.baseUrl.map(_ / "app" / "item").map(_.asString) + } +} diff --git a/modules/notification/impl/src/main/scala/docspell/notification/impl/context/TagsChangedCtx.scala b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/TagsChangedCtx.scala new file mode 100644 index 00000000..ee536482 --- /dev/null +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/context/TagsChangedCtx.scala @@ -0,0 +1,82 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.effect.Sync +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api.{Event, EventContext} +import docspell.notification.impl.AbstractEventContext +import docspell.notification.impl.context.BasicData._ +import docspell.notification.impl.context.Syntax._ +import docspell.store.records._ + +import doobie._ +import io.circe.Encoder +import io.circe.syntax._ +import yamusca.implicits._ + +final case class TagsChangedCtx(event: Event.TagsChanged, data: TagsChangedCtx.Data) + extends AbstractEventContext { + + val content = data.asJson + + val titleTemplate = mustache"{{eventType}} (by *{{account.user}}*)" + val bodyTemplate = + mustache"""{{#content}}{{#added}}{{#-first}}Adding {{/-first}}{{^-first}}, {{/-first}}*{{name}}*{{/added}}{{#removed}}{{#added}}{{#-first}};{{/-first}}{{/added}}{{#-first}} Removing {{/-first}}{{^-first}}, {{/-first}}*{{name}}*{{/removed}} on {{#items}}{{^-first}}, {{/-first}}{{#itemUrl}}[`{{name}}`]({{{itemUrl}}}/{{{id}}}){{/itemUrl}}{{^itemUrl}}`{{name}}`{{/itemUrl}}{{/items}}.{{/content}}""" + +} + +object TagsChangedCtx { + type Factory = EventContext.Factory[ConnectionIO, Event.TagsChanged] + + def apply: Factory = + EventContext.factory(ev => + for { + tagsAdded <- RTag.findAllByNameOrId(ev.added, ev.account.collective) + tagsRemov <- RTag.findAllByNameOrId(ev.removed, ev.account.collective) + now <- Timestamp.current[ConnectionIO] + items <- Item.find(ev.items, ev.account, now) + msg = TagsChangedCtx( + ev, + Data( + ev.account, + items.toList, + tagsAdded.map(Tag.apply).toList, + tagsRemov.map(Tag.apply).toList, + ev.itemUrl + ) + ) + } yield msg + ) + + def sample[F[_]: Sync]: EventContext.Example[F, Event.TagsChanged] = + EventContext.example(ev => + for { + items <- ev.items.traverse(Item.sample[F]) + added <- ev.added.traverse(Tag.sample[F]) + remov <- ev.removed.traverse(Tag.sample[F]) + } yield TagsChangedCtx( + ev, + Data(ev.account, items.toList, added, remov, ev.itemUrl) + ) + ) + + final case class Data( + account: AccountId, + items: List[Item], + added: List[Tag], + removed: List[Tag], + itemUrl: Option[String] + ) + + object Data { + implicit val jsonEncoder: Encoder[Data] = + io.circe.generic.semiauto.deriveEncoder + } +} diff --git a/modules/notification/impl/src/test/scala/docspell/notification/impl/context/TagsChangedCtxTest.scala b/modules/notification/impl/src/test/scala/docspell/notification/impl/context/TagsChangedCtxTest.scala new file mode 100644 index 00000000..4aded5c5 --- /dev/null +++ b/modules/notification/impl/src/test/scala/docspell/notification/impl/context/TagsChangedCtxTest.scala @@ -0,0 +1,75 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.notification.impl.context + +import cats.data.{NonEmptyList => Nel} +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api.Event +import docspell.notification.impl.context.BasicData._ + +import munit._ + +class TagsChangedCtxTest extends FunSuite { + + val url = LenientUri.unsafe("http://test") + val account = AccountId(id("user2"), id("user2")) + val tag = Tag(id("a-b-1"), "tag-red", Some("doctype")) + val item = Item( + id = id("item-1"), + name = "Report 2", + dateMillis = Timestamp.Epoch, + date = "2020-11-11", + direction = Direction.Incoming, + state = ItemState.created, + dueDateMillis = None, + dueDate = None, + source = "webapp", + overDue = false, + dueIn = None, + corrOrg = Some("Acme"), + notes = None + ) + + def id(str: String): Ident = Ident.unsafe(str) + + test("create tags changed message") { + val event = + Event.TagsChanged(account, Nel.of(id("item1")), List("tag-id"), Nil, url.some) + val ctx = TagsChangedCtx( + event, + TagsChangedCtx.Data(account, List(item), List(tag), Nil, url.some.map(_.asString)) + ) + + assertEquals(ctx.defaultTitle, "TagsChanged (by *user2*)") + assertEquals( + ctx.defaultBody, + "Adding *tag-red* on [`Report 2`](http://test/item-1)." + ) + } + test("create tags changed message") { + val event = Event.TagsChanged(account, Nel.of(id("item1")), Nil, Nil, url.some) + val ctx = TagsChangedCtx( + event, + TagsChangedCtx.Data( + account, + List(item), + List(tag), + List(tag.copy(name = "tag-blue")), + url.asString.some + ) + ) + + assertEquals(ctx.defaultTitle, "TagsChanged (by *user2*)") + assertEquals( + ctx.defaultBody, + "Adding *tag-red*; Removing *tag-blue* on [`Report 2`](http://test/item-1)." + ) + } + +} diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml index 66f53f57..56ee450e 100644 --- a/modules/restapi/src/main/resources/docspell-openapi.yml +++ b/modules/restapi/src/main/resources/docspell-openapi.yml @@ -36,6 +36,8 @@ paths: description: | Returns information about this software. responses: + 422: + description: BadRequest 200: description: Ok content: @@ -64,6 +66,8 @@ paths: schema: $ref: "#/components/schemas/UserPass" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -88,6 +92,8 @@ paths: schema: $ref: "#/components/schemas/SecondFactor" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -112,6 +118,8 @@ paths: parameters: - $ref: "#/components/parameters/providerId" responses: + 422: + description: BadRequest 302: description: Found. Redirect to external authentication provider 200: @@ -135,6 +143,8 @@ paths: parameters: - $ref: "#/components/parameters/providerId" responses: + 422: + description: BadRequest 303: description: See Other. Redirect to the webapp 200: @@ -155,6 +165,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/checksum" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -198,6 +210,8 @@ paths: type: string format: binary responses: + 422: + description: BadRequest 200: description: Ok content: @@ -241,6 +255,8 @@ paths: type: string format: binary responses: + 422: + description: BadRequest 200: description: Ok content: @@ -264,6 +280,8 @@ paths: security: - adminHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -282,6 +300,8 @@ paths: response is immediately returned and a task is submitted that will be executed by a job executor. responses: + 422: + description: BadRequest 200: description: Ok content: @@ -305,6 +325,8 @@ paths: parameters: - $ref: "#/components/parameters/checksum" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -347,6 +369,8 @@ paths: type: string format: binary responses: + 422: + description: BadRequest 200: description: Ok content: @@ -392,6 +416,8 @@ paths: type: string format: binary responses: + 422: + description: BadRequest 200: description: Ok content: @@ -414,6 +440,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -465,6 +493,8 @@ paths: type: string format: binary responses: + 422: + description: BadRequest 200: description: Ok content: @@ -489,6 +519,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/checksum" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -509,6 +541,8 @@ paths: schema: $ref: "#/components/schemas/Registration" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -532,6 +566,8 @@ paths: schema: $ref: "#/components/schemas/GenInvite" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -562,6 +598,8 @@ paths: schema: $ref: "#/components/schemas/ShareSecret" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -580,6 +618,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -597,6 +637,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok @@ -615,6 +657,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/sort" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -636,6 +680,8 @@ paths: schema: $ref: "#/components/schemas/Tag" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -657,6 +703,8 @@ paths: schema: $ref: "#/components/schemas/Tag" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -675,6 +723,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -698,6 +748,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/sort" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -721,6 +773,8 @@ paths: schema: $ref: "#/components/schemas/Organization" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -742,6 +796,8 @@ paths: schema: $ref: "#/components/schemas/Organization" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -760,6 +816,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -777,6 +835,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -801,6 +861,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/sort" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -824,6 +886,8 @@ paths: schema: $ref: "#/components/schemas/Person" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -845,6 +909,8 @@ paths: schema: $ref: "#/components/schemas/Person" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -863,6 +929,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -880,6 +948,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -901,6 +971,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/sort" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -922,6 +994,8 @@ paths: schema: $ref: "#/components/schemas/Equipment" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -943,6 +1017,8 @@ paths: schema: $ref: "#/components/schemas/Equipment" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -961,6 +1037,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -980,6 +1058,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1005,6 +1085,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/owning" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1026,6 +1108,8 @@ paths: schema: $ref: "#/components/schemas/NewFolder" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1044,6 +1128,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1066,6 +1152,8 @@ paths: schema: $ref: "#/components/schemas/NewFolder" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1083,6 +1171,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1102,6 +1192,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/userId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1120,6 +1212,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/userId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1137,6 +1231,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1153,6 +1249,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1173,6 +1271,8 @@ paths: schema: $ref: "#/components/schemas/CollectiveSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1190,6 +1290,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1206,6 +1308,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1227,6 +1331,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/contactKind" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1249,6 +1355,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1275,6 +1383,8 @@ paths: schema: $ref: "#/components/schemas/EmptyTrashSetting" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1292,6 +1402,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1313,6 +1425,8 @@ paths: schema: $ref: "#/components/schemas/User" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1334,6 +1448,8 @@ paths: schema: $ref: "#/components/schemas/User" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1352,6 +1468,8 @@ paths: parameters: - $ref: "#/components/parameters/username" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1372,6 +1490,8 @@ paths: parameters: - $ref: "#/components/parameters/username" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1394,6 +1514,8 @@ paths: schema: $ref: "#/components/schemas/PasswordChange" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1411,6 +1533,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1433,6 +1557,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1459,6 +1585,8 @@ paths: schema: $ref: "#/components/schemas/OtpConfirm" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1486,6 +1614,8 @@ paths: schema: $ref: "#/components/schemas/OtpConfirm" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1493,6 +1623,263 @@ paths: schema: $ref: "#/components/schemas/BasicResult" + /sec/notification/channel: + get: + operationId: "sec-notification-channel-get" + tags: [ Notification ] + summary: Return notification channels of the current user + description: | + Returns a list of notification channels for the current user. + security: + - authTokenHeader: [] + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/NotificationMail" + - $ref: "#/components/schemas/NotificationGotify" + - $ref: "#/components/schemas/NotificationMatrix" + - $ref: "#/components/schemas/NotificationHttp" + post: + operationId: "sec-notification-channel-post" + tags: [ Notification ] + summary: Create a new notification channel + description: | + Creates a new channel that can be used for notification. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/NotificationMail" + - $ref: "#/components/schemas/NotificationGotify" + - $ref: "#/components/schemas/NotificationMatrix" + - $ref: "#/components/schemas/NotificationHttp" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + put: + operationId: "sec-notification-channel-put" + tags: [ Notification ] + summary: Change a notification channel + description: | + Change details about a notification channel. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + oneOf: + - $ref: "#/components/schemas/NotificationMail" + - $ref: "#/components/schemas/NotificationGotify" + - $ref: "#/components/schemas/NotificationMatrix" + - $ref: "#/components/schemas/NotificationHttp" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + + /sec/notification/channel/{id}: + delete: + operationId: "sec-notification-channel-delete" + tags: [ Notification ] + summary: Delete a channel + description: | + Deletes the channel with the given id. This causes all hooks + of this channel to be deleted as well. + security: + - authTokenHeader: [] + parameters: + - $ref: "#/components/parameters/id" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + + /sec/notification/hook: + get: + operationId: "sec-notification-hook-get" + tags: [ Notification ] + summary: Return list of all hooks + description: | + Returns a list of all defined hooks for the current user. + security: + - authTokenHeader: [] + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + type: array + items: + $ref: "#/extraSchemas/NotificationHook" + post: + operationId: "sec-notification-hook-post" + tags: [ Notification ] + summary: Creates a new notification hook + description: | + Creates a new notification hook, that issues a request via the + given channel description. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/extraSchemas/NotificationHook" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + put: + operationId: "sec-notification-hook-put" + tags: [ Notification ] + summary: Updates a notification hook + description: | + Updates the hook details. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/extraSchemas/NotificationHook" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + + /sec/notification/hook/{id}: + delete: + operationId: "sec-notification-hook-delete" + tags: [ Notification ] + summary: Delete a hook + description: | + Deletes the hook with the given id. + security: + - authTokenHeader: [] + parameters: + - $ref: "#/components/parameters/id" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + + /sec/notification/hook/sendTestEvent: + post: + operationId: "sec-notification-hook-sendtestevent-post" + tags: [ Notification ] + summary: Test a webhook + description: | + Tests the webhook specified in the body by applying it to a + sample event. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/extraSchemas/NotificationHook" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/NotificationChannelTestResult" + /sec/notification/hook/verifyJsonFilter: + post: + operationId: "sec-notification-hook-verifyjsonfilter-post" + tags: [ Notification ] + summary: Verify a json filter expression + description: | + Parses the given value into a JSON mini query. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/StringValue" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + + + /sec/notification/event/sample: + post: + operationId: "sec-notification-sample-event-post" + tags: [ Notification ] + summary: Provide sample event data + description: | + Given an event type, generate some random sample of what would + be send on such an event. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/NotificationSampleEventReq" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: {} + /sec/clientSettings/{clientId}: parameters: - $ref: "#/components/parameters/clientId" @@ -1508,6 +1895,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1535,6 +1924,8 @@ paths: application/json: schema: {} responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1551,6 +1942,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1575,6 +1968,8 @@ paths: schema: $ref: "#/components/schemas/ItemQuery" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1597,6 +1992,8 @@ paths: schema: $ref: "#/components/schemas/ItemQuery" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1615,6 +2012,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1634,6 +2033,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok headers: @@ -1663,6 +2064,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1692,6 +2095,8 @@ paths: responses: 303: description: See Other + 422: + description: BadRequest 200: description: Ok /share/attachment/{id}/preview: @@ -1731,6 +2136,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/withFallback" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1757,6 +2164,8 @@ paths: schema: $ref: "#/components/schemas/ResetPassword" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1781,6 +2190,8 @@ paths: schema: $ref: "#/components/schemas/ResetPassword" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1807,6 +2218,8 @@ paths: security: - adminHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1838,6 +2251,8 @@ paths: security: - adminHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1855,6 +2270,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1876,6 +2293,8 @@ paths: schema: $ref: "#/components/schemas/SourceTagIn" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1897,6 +2316,8 @@ paths: schema: $ref: "#/components/schemas/SourceTagIn" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1916,6 +2337,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1936,6 +2359,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/owningShare" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1956,6 +2381,8 @@ paths: schema: $ref: "#/components/schemas/ShareData" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -1982,6 +2409,8 @@ paths: schema: $ref: "#/components/schemas/SimpleShareMail" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2000,6 +2429,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2020,6 +2451,8 @@ paths: schema: $ref: "#/components/schemas/ShareData" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2035,6 +2468,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2063,6 +2498,8 @@ paths: - $ref: "#/components/parameters/withDetails" - $ref: "#/components/parameters/searchMode" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2088,6 +2525,8 @@ paths: schema: $ref: "#/components/schemas/ItemQuery" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2120,6 +2559,8 @@ paths: schema: $ref: "#/components/schemas/ItemQuery" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2143,6 +2584,8 @@ paths: schema: $ref: "#/components/schemas/ItemQuery" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2162,6 +2605,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/searchMode" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2181,6 +2626,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2200,6 +2647,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2219,6 +2668,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2247,6 +2698,8 @@ paths: schema: $ref: "#/components/schemas/StringList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2273,6 +2726,8 @@ paths: schema: $ref: "#/components/schemas/Tag" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2299,6 +2754,8 @@ paths: schema: $ref: "#/components/schemas/StringList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2327,6 +2784,8 @@ paths: schema: $ref: "#/components/schemas/StringList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2352,6 +2811,8 @@ paths: schema: $ref: "#/components/schemas/StringList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2376,6 +2837,8 @@ paths: schema: $ref: "#/components/schemas/DirectionValue" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2402,6 +2865,8 @@ paths: schema: $ref: "#/components/schemas/OptionalId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2425,6 +2890,8 @@ paths: schema: $ref: "#/components/schemas/OptionalId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2448,6 +2915,8 @@ paths: schema: $ref: "#/components/schemas/Organization" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2471,6 +2940,8 @@ paths: schema: $ref: "#/components/schemas/OptionalId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2494,6 +2965,8 @@ paths: schema: $ref: "#/components/schemas/Person" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2517,6 +2990,8 @@ paths: schema: $ref: "#/components/schemas/OptionalId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2540,6 +3015,8 @@ paths: schema: $ref: "#/components/schemas/Person" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2563,6 +3040,8 @@ paths: schema: $ref: "#/components/schemas/OptionalId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2586,6 +3065,8 @@ paths: schema: $ref: "#/components/schemas/Equipment" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2609,6 +3090,8 @@ paths: schema: $ref: "#/components/schemas/OptionalText" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2632,6 +3115,8 @@ paths: schema: $ref: "#/components/schemas/OptionalText" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2651,6 +3136,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2670,6 +3157,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2693,6 +3182,8 @@ paths: schema: $ref: "#/components/schemas/OptionalDate" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2716,6 +3207,8 @@ paths: schema: $ref: "#/components/schemas/OptionalDate" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2736,6 +3229,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2756,6 +3251,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok 404: @@ -2777,6 +3274,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/withFallback" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2804,6 +3303,8 @@ paths: schema: $ref: "#/components/schemas/CustomFieldValue" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2824,6 +3325,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/itemId" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2854,6 +3357,8 @@ paths: schema: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2881,6 +3386,8 @@ paths: schema: $ref: "#/components/schemas/MoveAttachment" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2919,6 +3426,8 @@ paths: schema: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2942,6 +3451,8 @@ paths: schema: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2965,6 +3476,8 @@ paths: schema: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -2991,6 +3504,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRefs" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3013,6 +3528,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRefs" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3036,6 +3553,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRefs" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3061,6 +3580,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndName" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3086,6 +3607,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRef" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3110,6 +3633,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndDirection" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3135,6 +3660,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndDate" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3160,6 +3687,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndDate" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3185,6 +3714,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRef" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3210,6 +3741,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRef" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3235,6 +3768,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRef" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3260,6 +3795,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndRef" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3283,6 +3820,8 @@ paths: schema: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3306,6 +3845,8 @@ paths: schema: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3333,6 +3874,8 @@ paths: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3358,6 +3901,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndFieldValue" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3381,6 +3926,8 @@ paths: schema: $ref: "#/components/schemas/ItemsAndName" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3407,6 +3954,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3425,6 +3974,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok headers: @@ -3454,6 +4005,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3477,6 +4030,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok headers: @@ -3508,6 +4063,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3531,6 +4088,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok headers: @@ -3562,6 +4121,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3582,6 +4143,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok 404: @@ -3603,6 +4166,8 @@ paths: - $ref: "#/components/parameters/id" - $ref: "#/components/parameters/withFallback" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3622,6 +4187,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3642,6 +4209,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3670,6 +4239,8 @@ paths: responses: 303: description: See Other + 422: + description: BadRequest 200: description: Ok /sec/attachment/{id}/name: @@ -3691,6 +4262,8 @@ paths: schema: $ref: "#/components/schemas/OptionalText" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3714,6 +4287,8 @@ paths: schema: $ref: "#/components/schemas/IdList" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3733,6 +4308,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3753,6 +4330,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3777,6 +4356,8 @@ paths: schema: $ref: "#/components/schemas/JobPriority" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3802,6 +4383,8 @@ paths: parameters: - $ref: "#/components/parameters/q" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3822,6 +4405,8 @@ paths: schema: $ref: "#/components/schemas/EmailSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3841,6 +4426,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3861,6 +4448,8 @@ paths: schema: $ref: "#/components/schemas/EmailSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3876,6 +4465,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3900,6 +4491,8 @@ paths: parameters: - $ref: "#/components/parameters/q" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3920,6 +4513,8 @@ paths: schema: $ref: "#/components/schemas/ImapSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3939,6 +4534,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3959,6 +4556,8 @@ paths: schema: $ref: "#/components/schemas/ImapSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -3974,6 +4573,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4001,6 +4602,8 @@ paths: schema: $ref: "#/components/schemas/SimpleMail" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4020,6 +4623,8 @@ paths: parameters: - $ref: "#/components/parameters/id" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4038,6 +4643,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4053,6 +4660,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4075,12 +4684,15 @@ paths: schema: $ref: "#/components/schemas/CalEventCheck" responses: + 422: + description: BadRequest 200: description: Ok content: application/json: schema: $ref: "#/components/schemas/CalEventCheckResult" + /sec/usertask/notifydueitems: get: operationId: "sec-usertask-notify-all" @@ -4094,12 +4706,16 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: application/json: schema: - $ref: "#/components/schemas/NotificationSettingsList" + type: array + items: + $ref: "#/extraSchemas/PeriodicDueItemsSettings" post: operationId: "sec-usertask-notify-new" tags: [ User Tasks ] @@ -4113,8 +4729,10 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/NotificationSettings" + $ref: "#/extraSchemas/PeriodicDueItemsSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4134,8 +4752,10 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/NotificationSettings" + $ref: "#/extraSchemas/PeriodicDueItemsSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4155,12 +4775,14 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: application/json: schema: - $ref: "#/components/schemas/NotificationSettings" + $ref: "#/extraSchemas/PeriodicDueItemsSettings" delete: operationId: "sec-usertask-notify-delete" tags: [ User Tasks ] @@ -4171,6 +4793,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4192,8 +4816,141 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/NotificationSettings" + $ref: "#/extraSchemas/PeriodicDueItemsSettings" responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + + /sec/usertask/periodicquery: + get: + operationId: "sec-usertask-periodic-query-all" + tags: [ User Tasks ] + summary: Get settings for PeriodicQuery task + description: | + Return all current settings of the authenticated user. + security: + - authTokenHeader: [] + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + type: array + items: + $ref: "#/extraSchemas/PeriodicQuerySettings" + post: + operationId: "sec-usertask-periodic-query-new" + tags: [ User Tasks ] + summary: Create settings for PeriodicQuery task + description: | + Create a new periodic-query task of the authenticated user. + The id field in the input is ignored. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/extraSchemas/PeriodicQuerySettings" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + put: + operationId: "sec-usertask-periodic-query-edit" + tags: [ User Tasks ] + summary: Change settings for PeriodicQuery task + description: | + Change the settings for a periodic-query task. The task is + looked up by its id. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/extraSchemas/PeriodicQuerySettings" + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + /sec/usertask/periodicquery/{id}: + parameters: + - $ref: "#/components/parameters/id" + get: + operationId: "sec-usertask-periodic-query-get-details" + tags: [ User Tasks ] + summary: Get periodic query for a specific task + description: | + Return the current settings for a single periodic-query task + of the authenticated user. + security: + - authTokenHeader: [] + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/extraSchemas/PeriodicQuerySettings" + delete: + operationId: "sec-usertask-periodic-query-delete" + tags: [ User Tasks ] + summary: Delete a specific periodic-query task + description: | + Delete the settings to a periodic-query task of the + authenticated user. + security: + - authTokenHeader: [] + responses: + 422: + description: BadRequest + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + + /sec/usertask/periodicquery/startonce: + post: + operationId: "sec-usertask-periodic-query-start-now" + tags: [ User Tasks ] + summary: Start the PeriodicQuery task once + description: | + Starts the periodic-query task just once, discarding the + schedule and not updating the periodic task. + security: + - authTokenHeader: [] + requestBody: + content: + application/json: + schema: + $ref: "#/extraSchemas/PeriodicQuerySettings" + responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4214,6 +4971,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4235,6 +4994,8 @@ paths: schema: $ref: "#/components/schemas/ScanMailboxSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4256,6 +5017,8 @@ paths: schema: $ref: "#/components/schemas/ScanMailboxSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4276,6 +5039,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4292,6 +5057,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4315,6 +5082,8 @@ paths: schema: $ref: "#/components/schemas/ScanMailboxSettings" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4338,6 +5107,8 @@ paths: - $ref: "#/components/parameters/q" - $ref: "#/components/parameters/sort" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4358,6 +5129,8 @@ paths: schema: $ref: "#/components/schemas/NewCustomField" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4377,6 +5150,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4402,6 +5177,8 @@ paths: schema: $ref: "#/components/schemas/NewCustomField" responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4417,6 +5194,8 @@ paths: security: - authTokenHeader: [] responses: + 422: + description: BadRequest 200: description: Ok content: @@ -4427,6 +5206,136 @@ paths: components: schemas: + StringValue: + description: | + A generic string value + required: + - value + properties: + value: + type: string + + NotificationSampleEventReq: + description: | + An event type. + required: + - eventType + properties: + eventType: + type: string + format: eventtype + NotificationChannelTestResult: + description: | + Results from running a sample event. + required: + - success + - messages + properties: + success: + type: boolean + messages: + type: array + items: + type: string + NotificationChannelRef: + description: | + A reference to a channel. + required: + - id + - channelType + properties: + id: + type: string + format: ident + channelType: + type: string + format: channeltype + NotificationMatrix: + description: | + A notification channel for matrix. + required: + - id + - channelType + - homeServer + - roomId + - accessToken + properties: + id: + type: string + format: ident + channelType: + type: string + format: channeltype + homeServer: + type: string + format: uri + roomId: + type: string + accessToken: + type: string + format: password + NotificationGotify: + description: | + A notification channel for gotify. + required: + - id + - channelType + - url + - appKey + properties: + id: + type: string + format: ident + channelType: + type: string + format: channeltype + url: + type: string + format: uri + appKey: + type: string + format: password + NotificationHttp: + description: | + A notification channel for receiving a generic http request. + required: + - id + - channelType + - url + properties: + id: + type: string + format: ident + channelType: + type: string + format: channeltype + url: + type: string + format: uri + NotificationMail: + description: | + A notification channel for receiving e-mails. + required: + - id + - channelType + - connection + - recipients + properties: + id: + type: string + format: ident + channelType: + type: string + format: channeltype + connection: + type: string + format: ident + recipients: + type: array + items: + type: string + format: ident + ShareSecret: description: | The secret (the share id + optional password) to access a @@ -5172,70 +6081,6 @@ components: properties: event: type: string - NotificationSettingsList: - description: | - A list of notification settings. - required: - - items - properties: - items: - type: array - items: - $ref: "#/components/schemas/NotificationSettings" - NotificationSettings: - description: | - Settings for notifying about due items. - required: - - id - - enabled - - smtpConnection - - recipients - - schedule - - remindDays - - capOverdue - - tagsInclude - - tagsExclude - properties: - id: - type: string - format: ident - enabled: - type: boolean - summary: - type: string - smtpConnection: - type: string - format: ident - recipients: - type: array - items: - type: string - format: ident - schedule: - type: string - format: calevent - remindDays: - type: integer - format: int32 - description: | - Used to restrict items by their due dates. All items with - a due date lower than (now + remindDays) are searched. - capOverdue: - type: boolean - description: | - If this is true, the search is also restricted to due - dates greater than `now - remindDays'. Otherwise, due date - are not restricted in that direction (only lower than `now - + remindDays' applies) and it is expected to restrict it - more using custom tags. - tagsInclude: - type: array - items: - $ref: "#/components/schemas/Tag" - tagsExclude: - type: array - items: - $ref: "#/components/schemas/Tag" SentMails: description: | A list of sent mails. @@ -6917,3 +7762,133 @@ components: schema: type: string format: ident + +# sadly no generator support for these. +# Changes here requires corresponding changes in: +# - NotificationHook.elm +# - routes.model.* +extraSchemas: + NotificationHook: + description: | + Describes a notifcation hook. There must be exactly one channel + specified, so either use a `channelRef` or one `channel`. + required: + - id + - enabled + - channel + - events + - allEvents + properties: + id: + type: string + format: ident + enabled: + type: boolean + channel: + oneOf: + - $ref: "#/components/schemas/NotificationMail" + - $ref: "#/components/schemas/NotificationGotify" + - $ref: "#/components/schemas/NotificationMatrix" + - $ref: "#/components/schemas/NotificationHttp" + - $ref: "#/components/schemas/NotificationChannelRef" + allEvents: + type: boolean + eventFilter: + type: string + format: jsonminiq + description: | + A filter expression that is applied to the event to be able + to ignore a subset of them. See its + [documentation](https://docspell.org/docs/jsonminiquery/). + events: + type: array + items: + type: string + format: eventtype + enum: + - tagsAdded + - tagsSet + + PeriodicQuerySettings: + description: | + Settings for the periodc-query task. + required: + - id + - enabled + - channel + - query + - schedule + properties: + id: + type: string + format: ident + enabled: + type: boolean + summary: + type: string + channel: + oneOf: + - $ref: "#/components/schemas/NotificationMail" + - $ref: "#/components/schemas/NotificationGotify" + - $ref: "#/components/schemas/NotificationMatrix" + - $ref: "#/components/schemas/NotificationHttp" + - $ref: "#/components/schemas/NotificationChannelRef" + schedule: + type: string + format: calevent + query: + type: string + format: itemquery + + PeriodicDueItemsSettings: + description: | + Settings for notifying about due items. + required: + - id + - enabled + - channel + - schedule + - remindDays + - capOverdue + - tagsInclude + - tagsExclude + properties: + id: + type: string + format: ident + enabled: + type: boolean + summary: + type: string + channel: + oneOf: + - $ref: "#/components/schemas/NotificationMail" + - $ref: "#/components/schemas/NotificationGotify" + - $ref: "#/components/schemas/NotificationMatrix" + - $ref: "#/components/schemas/NotificationHttp" + - $ref: "#/components/schemas/NotificationChannelRef" + schedule: + type: string + format: calevent + remindDays: + type: integer + format: int32 + description: | + Used to restrict items by their due dates. All items with + a due date lower than (now + remindDays) are searched. + capOverdue: + type: boolean + description: | + If this is true, the search is also restricted to due + dates greater than `now - remindDays'. Otherwise, due date + are not restricted in that direction (only lower than `now + + remindDays' applies) and it is expected to restrict it + more using custom tags. + tagsInclude: + type: array + items: + $ref: "#/components/schemas/Tag" + tagsExclude: + type: array + items: + $ref: "#/components/schemas/Tag" diff --git a/modules/restapi/src/main/scala/docspell/restapi/codec/ChannelEihterCodec.scala b/modules/restapi/src/main/scala/docspell/restapi/codec/ChannelEihterCodec.scala new file mode 100644 index 00000000..73354b88 --- /dev/null +++ b/modules/restapi/src/main/scala/docspell/restapi/codec/ChannelEihterCodec.scala @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restapi.codec + +import docspell.notification.api.ChannelRef +import docspell.restapi.model._ + +import io.circe.syntax._ +import io.circe.{Decoder, Encoder} + +trait ChannelEitherCodec { + + implicit val channelDecoder: Decoder[Either[ChannelRef, NotificationChannel]] = + NotificationChannel.jsonDecoder.either(ChannelRef.jsonDecoder).map(_.swap) + + implicit val channelEncoder: Encoder[Either[ChannelRef, NotificationChannel]] = + Encoder.instance(_.fold(_.asJson, _.asJson)) + +} + +object ChannelEitherCodec extends ChannelEitherCodec diff --git a/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala new file mode 100644 index 00000000..843fb17a --- /dev/null +++ b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala @@ -0,0 +1,130 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restapi.model + +import cats.data.NonEmptyList +import cats.implicits._ + +import docspell.notification.api.Channel +import docspell.notification.api.ChannelType +import docspell.restapi.model._ + +import emil.MailAddress +import emil.javamail.syntax._ +import io.circe.{Decoder, Encoder} + +sealed trait NotificationChannel { + def fold[A]( + f1: NotificationMail => A, + f2: NotificationGotify => A, + f3: NotificationMatrix => A, + f4: NotificationHttp => A + ): A +} + +object NotificationChannel { + final case class Mail(c: NotificationMail) extends NotificationChannel { + def fold[A]( + f1: NotificationMail => A, + f2: NotificationGotify => A, + f3: NotificationMatrix => A, + f4: NotificationHttp => A + ): A = f1(c) + } + final case class Gotify(c: NotificationGotify) extends NotificationChannel { + def fold[A]( + f1: NotificationMail => A, + f2: NotificationGotify => A, + f3: NotificationMatrix => A, + f4: NotificationHttp => A + ): A = f2(c) + } + final case class Matrix(c: NotificationMatrix) extends NotificationChannel { + def fold[A]( + f1: NotificationMail => A, + f2: NotificationGotify => A, + f3: NotificationMatrix => A, + f4: NotificationHttp => A + ): A = f3(c) + } + final case class Http(c: NotificationHttp) extends NotificationChannel { + def fold[A]( + f1: NotificationMail => A, + f2: NotificationGotify => A, + f3: NotificationMatrix => A, + f4: NotificationHttp => A + ): A = f4(c) + } + + def mail(c: NotificationMail): NotificationChannel = Mail(c) + def gotify(c: NotificationGotify): NotificationChannel = Gotify(c) + def matrix(c: NotificationMatrix): NotificationChannel = Matrix(c) + def http(c: NotificationHttp): NotificationChannel = Http(c) + + def convert(c: NotificationChannel): Either[Throwable, Channel] = + c.fold( + mail => + mail.recipients + .traverse(MailAddress.parse) + .map(NonEmptyList.fromList) + .flatMap(_.toRight("No recipients given!")) + .leftMap(new IllegalArgumentException(_)) + .map(rec => Channel.Mail(mail.id, mail.connection, rec)), + gotify => Right(Channel.Gotify(gotify.id, gotify.url, gotify.appKey)), + matrix => + Right( + Channel + .Matrix(matrix.id, matrix.homeServer, matrix.roomId, matrix.accessToken) + ), + http => Right(Channel.Http(http.id, http.url)) + ) + + def convert(c: Channel): NotificationChannel = + c.fold( + m => + mail { + NotificationMail( + m.id, + ChannelType.Mail, + m.connection, + m.recipients.toList.map(_.displayString) + ) + }, + g => gotify(NotificationGotify(g.id, ChannelType.Gotify, g.url, g.appKey)), + m => + matrix( + NotificationMatrix( + m.id, + ChannelType.Matrix, + m.homeServer, + m.roomId, + m.accessToken + ) + ), + h => http(NotificationHttp(h.id, ChannelType.Http, h.url)) + ) + + implicit val jsonDecoder: Decoder[NotificationChannel] = + ChannelType.jsonDecoder.at("channelType").flatMap { + case ChannelType.Mail => Decoder[NotificationMail].map(mail) + case ChannelType.Gotify => Decoder[NotificationGotify].map(gotify) + case ChannelType.Matrix => Decoder[NotificationMatrix].map(matrix) + case ChannelType.Http => Decoder[NotificationHttp].map(http) + } + + implicit val jsonEncoder: Encoder[NotificationChannel] = + Encoder.instance { + case NotificationChannel.Mail(c) => + Encoder[NotificationMail].apply(c) + case NotificationChannel.Gotify(c) => + Encoder[NotificationGotify].apply(c) + case NotificationChannel.Matrix(c) => + Encoder[NotificationMatrix].apply(c) + case NotificationChannel.Http(c) => + Encoder[NotificationHttp].apply(c) + } +} diff --git a/modules/restapi/src/main/scala/docspell/restapi/model/NotificationHook.scala b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationHook.scala new file mode 100644 index 00000000..172a2c5f --- /dev/null +++ b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationHook.scala @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restapi.model + +import docspell.common._ +import docspell.jsonminiq.JsonMiniQuery +import docspell.notification.api.{ChannelRef, EventType} +import docspell.restapi.codec.ChannelEitherCodec + +import io.circe.{Decoder, Encoder} + +// this must comply to the definition in openapi.yml in `extraSchemas` +final case class NotificationHook( + id: Ident, + enabled: Boolean, + channel: Either[ChannelRef, NotificationChannel], + allEvents: Boolean, + eventFilter: Option[JsonMiniQuery], + events: List[EventType] +) + +object NotificationHook { + import ChannelEitherCodec._ + + implicit val jsonDecoder: Decoder[NotificationHook] = + io.circe.generic.semiauto.deriveDecoder + implicit val jsonEncoder: Encoder[NotificationHook] = + io.circe.generic.semiauto.deriveEncoder +} diff --git a/modules/restapi/src/main/scala/docspell/restapi/model/PeriodicDueItemsSettings.scala b/modules/restapi/src/main/scala/docspell/restapi/model/PeriodicDueItemsSettings.scala new file mode 100644 index 00000000..5f4b7fac --- /dev/null +++ b/modules/restapi/src/main/scala/docspell/restapi/model/PeriodicDueItemsSettings.scala @@ -0,0 +1,35 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restapi.model + +import docspell.common._ +import docspell.restapi.model._ + +import com.github.eikek.calev.CalEvent +import com.github.eikek.calev.circe.CalevCirceCodec._ +import io.circe.generic.semiauto +import io.circe.{Decoder, Encoder} + +// this must comply to the definition in openapi.yml in `extraSchemas` +final case class PeriodicDueItemsSettings( + id: Ident, + enabled: Boolean, + summary: Option[String], + channel: NotificationChannel, + schedule: CalEvent, + remindDays: Int, + capOverdue: Boolean, + tagsInclude: List[Tag], + tagsExclude: List[Tag] +) +object PeriodicDueItemsSettings { + + implicit val jsonDecoder: Decoder[PeriodicDueItemsSettings] = + semiauto.deriveDecoder[PeriodicDueItemsSettings] + implicit val jsonEncoder: Encoder[PeriodicDueItemsSettings] = + semiauto.deriveEncoder[PeriodicDueItemsSettings] +} diff --git a/modules/restapi/src/main/scala/docspell/restapi/model/PeriodicQuerySettings.scala b/modules/restapi/src/main/scala/docspell/restapi/model/PeriodicQuerySettings.scala new file mode 100644 index 00000000..5045c62f --- /dev/null +++ b/modules/restapi/src/main/scala/docspell/restapi/model/PeriodicQuerySettings.scala @@ -0,0 +1,35 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restapi.model + +import docspell.common._ +import docspell.query.ItemQuery +import docspell.restapi.codec.ItemQueryJson._ + +import com.github.eikek.calev.CalEvent +import com.github.eikek.calev.circe.CalevCirceCodec._ +import io.circe.generic.semiauto +import io.circe.{Decoder, Encoder} + +// this must comply to the definition in openapi.yml in `extraSchemas` +final case class PeriodicQuerySettings( + id: Ident, + summary: Option[String], + enabled: Boolean, + channel: NotificationChannel, + query: ItemQuery, + schedule: CalEvent +) {} + +object PeriodicQuerySettings { + + implicit val jsonDecoder: Decoder[PeriodicQuerySettings] = + semiauto.deriveDecoder + + implicit val jsonEncoder: Encoder[PeriodicQuerySettings] = + semiauto.deriveEncoder +} diff --git a/modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala b/modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala new file mode 100644 index 00000000..e288b3d1 --- /dev/null +++ b/modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala @@ -0,0 +1,62 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restapi.model + +import docspell.common._ +import docspell.notification.api.ChannelRef +import docspell.notification.api.ChannelType + +import io.circe.Decoder +import io.circe.parser +import munit._ + +class NotificationCodecTest extends FunSuite { + + def parse[A: Decoder](str: String): A = + parser.parse(str).fold(throw _, identity).as[A].fold(throw _, identity) + + def id(str: String): Ident = + Ident.unsafe(str) + + test("decode with channelref") { + val json = """{"id":"", + "enabled": true, + "channel": {"id":"abcde", "channelType":"matrix"}, + "allEvents": false, + "events": ["TagsChanged", "SetFieldValue"] +}""" + + val hook = parse[NotificationHook](json) + assertEquals(hook.enabled, true) + assertEquals(hook.channel, Left(ChannelRef(id("abcde"), ChannelType.Matrix))) + } + + test("decode with gotify data") { + val json = """{"id":"", + "enabled": true, + "channel": {"id":"", "channelType":"gotify", "url":"http://test.gotify.com", "appKey": "abcde"}, + "allEvents": false, + "eventFilter": null, + "events": ["TagsChanged", "SetFieldValue"] +}""" + val hook = parse[NotificationHook](json) + assertEquals(hook.enabled, true) + assertEquals( + hook.channel, + Right( + NotificationChannel.Gotify( + NotificationGotify( + id(""), + ChannelType.Gotify, + LenientUri.unsafe("http://test.gotify.com"), + Password("abcde") + ) + ) + ) + ) + } +} diff --git a/modules/restserver/src/main/resources/logback.xml b/modules/restserver/src/main/resources/logback.xml index f9b2d921..29d65bca 100644 --- a/modules/restserver/src/main/resources/logback.xml +++ b/modules/restserver/src/main/resources/logback.xml @@ -9,7 +9,7 @@ - + diff --git a/modules/restserver/src/main/scala/docspell/restserver/RestApp.scala b/modules/restserver/src/main/scala/docspell/restserver/RestApp.scala index 68383b0a..44c80eaa 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/RestApp.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/RestApp.scala @@ -6,11 +6,23 @@ package docspell.restserver +import fs2.Stream + import docspell.backend.BackendApp trait RestApp[F[_]] { + /** Access to the configuration used to build backend services. */ def config: Config + /** Access to all backend services */ def backend: BackendApp[F] + + /** Stream consuming events (async) originating in this application. */ + def eventConsume(maxConcurrent: Int): Stream[F, Nothing] + + /** Stream consuming messages from topics (pubsub) and forwarding them to the frontend + * via websocket. + */ + def subscriptions: Stream[F, Nothing] } diff --git a/modules/restserver/src/main/scala/docspell/restserver/RestAppImpl.scala b/modules/restserver/src/main/scala/docspell/restserver/RestAppImpl.scala index 65a5ad5e..902bb8b4 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/RestAppImpl.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/RestAppImpl.scala @@ -7,18 +7,36 @@ package docspell.restserver import cats.effect._ +import fs2.Stream +import fs2.concurrent.Topic import docspell.backend.BackendApp import docspell.common.Logger import docspell.ftsclient.FtsClient import docspell.ftssolr.SolrFtsClient +import docspell.notification.api.NotificationModule +import docspell.notification.impl.NotificationModuleImpl import docspell.pubsub.api.{PubSub, PubSubT} +import docspell.restserver.ws.OutputEvent import docspell.store.Store +import emil.javamail.JavaMailEmil import org.http4s.client.Client -final class RestAppImpl[F[_]](val config: Config, val backend: BackendApp[F]) - extends RestApp[F] {} +final class RestAppImpl[F[_]: Async]( + val config: Config, + val backend: BackendApp[F], + notificationMod: NotificationModule[F], + wsTopic: Topic[F, OutputEvent], + pubSub: PubSubT[F] +) extends RestApp[F] { + + def eventConsume(maxConcurrent: Int): Stream[F, Nothing] = + notificationMod.consumeAllEvents(maxConcurrent) + + def subscriptions: Stream[F, Nothing] = + Subscriptions[F](wsTopic, pubSub) +} object RestAppImpl { @@ -26,14 +44,21 @@ object RestAppImpl { cfg: Config, store: Store[F], httpClient: Client[F], - pubSub: PubSub[F] + pubSub: PubSub[F], + wsTopic: Topic[F, OutputEvent] ): Resource[F, RestApp[F]] = { val logger = Logger.log4s(org.log4s.getLogger(s"restserver-${cfg.appId.id}")) for { ftsClient <- createFtsClient(cfg)(httpClient) pubSubT = PubSubT(pubSub, logger) - backend <- BackendApp.create[F](cfg.backend, store, ftsClient, pubSubT) - app = new RestAppImpl[F](cfg, backend) + javaEmil = JavaMailEmil(cfg.backend.mailSettings) + notificationMod <- Resource.eval( + NotificationModuleImpl[F](store, javaEmil, httpClient, 200) + ) + backend <- BackendApp + .create[F](store, javaEmil, ftsClient, pubSubT, notificationMod) + + app = new RestAppImpl[F](cfg, backend, notificationMod, wsTopic, pubSubT) } yield app } diff --git a/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala b/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala index 663cc962..aaecc0dd 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala @@ -50,10 +50,11 @@ object RestServer { server = Stream - .resource(createApp(cfg, pools)) + .resource(createApp(cfg, pools, wsTopic)) .flatMap { case (restApp, pubSub, httpClient, setting) => Stream( - Subscriptions(wsTopic, restApp.backend.pubSub), + restApp.subscriptions, + restApp.eventConsume(2), BlazeServerBuilder[F] .bindHttp(cfg.bind.port, cfg.bind.address) .withoutBanner @@ -71,8 +72,12 @@ object RestServer { def createApp[F[_]: Async]( cfg: Config, - pools: Pools - ): Resource[F, (RestApp[F], NaivePubSub[F], Client[F], RInternalSetting)] = + pools: Pools, + wsTopic: Topic[F, OutputEvent] + ): Resource[ + F, + (RestApp[F], NaivePubSub[F], Client[F], RInternalSetting) + ] = for { httpClient <- BlazeClientBuilder[F].resource store <- Store.create[F]( @@ -86,7 +91,7 @@ object RestServer { store, httpClient )(Topics.all.map(_.topic)) - restApp <- RestAppImpl.create[F](cfg, store, httpClient, pubSub) + restApp <- RestAppImpl.create[F](cfg, store, httpClient, pubSub, wsTopic) } yield (restApp, pubSub, httpClient, setting) def createHttpApp[F[_]: Async]( @@ -150,7 +155,7 @@ object RestServer { "collective" -> CollectiveRoutes(restApp.backend, token), "queue" -> JobQueueRoutes(restApp.backend, token), "item" -> ItemRoutes(cfg, restApp.backend, token), - "items" -> ItemMultiRoutes(restApp.backend, token), + "items" -> ItemMultiRoutes(cfg, restApp.backend, token), "attachment" -> AttachmentRoutes(restApp.backend, token), "attachments" -> AttachmentMultiRoutes(restApp.backend, token), "upload" -> UploadRoutes.secured(restApp.backend, cfg, token), @@ -161,11 +166,13 @@ object RestServer { "share" -> ShareRoutes.manage(restApp.backend, token), "usertask/notifydueitems" -> NotifyDueItemsRoutes(cfg, restApp.backend, token), "usertask/scanmailbox" -> ScanMailboxRoutes(restApp.backend, token), + "usertask/periodicquery" -> PeriodicQueryRoutes(cfg, restApp.backend, token), "calevent/check" -> CalEventCheckRoutes(), "fts" -> FullTextIndexRoutes.secured(cfg, restApp.backend, token), "folder" -> FolderRoutes(restApp.backend, token), "customfield" -> CustomFieldRoutes(restApp.backend, token), - "clientSettings" -> ClientSettingsRoutes(restApp.backend, token) + "clientSettings" -> ClientSettingsRoutes(restApp.backend, token), + "notification" -> NotificationRoutes(cfg, restApp.backend, token) ) def openRoutes[F[_]: Async]( diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala index ae08e6c4..bc2dafc0 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemMultiRoutes.scala @@ -14,7 +14,9 @@ import docspell.backend.auth.AuthToken import docspell.backend.ops.OCustomFields.{RemoveValue, SetValue} import docspell.common._ import docspell.restapi.model._ +import docspell.restserver.Config import docspell.restserver.conv.{Conversions, MultiIdSupport} +import docspell.restserver.http4s.ClientRequestInfo import org.http4s.HttpRoutes import org.http4s.circe.CirceEntityDecoder._ @@ -26,6 +28,7 @@ object ItemMultiRoutes extends MultiIdSupport { private[this] val log4sLogger = getLogger def apply[F[_]: Async]( + cfg: Config, backend: BackendApp[F], user: AuthToken ): HttpRoutes[F] = { @@ -66,7 +69,9 @@ object ItemMultiRoutes extends MultiIdSupport { json.refs, user.account.collective ) - resp <- Ok(Conversions.basicResult(res, "Tags updated")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tags updated")) } yield resp case req @ POST -> Root / "tags" => @@ -78,7 +83,9 @@ object ItemMultiRoutes extends MultiIdSupport { json.refs, user.account.collective ) - resp <- Ok(Conversions.basicResult(res, "Tags added.")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tags added.")) } yield resp case req @ POST -> Root / "tagsremove" => @@ -90,7 +97,9 @@ object ItemMultiRoutes extends MultiIdSupport { json.refs, user.account.collective ) - resp <- Ok(Conversions.basicResult(res, "Tags removed")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tags removed")) } yield resp case req @ PUT -> Root / "name" => @@ -205,7 +214,9 @@ object ItemMultiRoutes extends MultiIdSupport { items, SetValue(json.field.field, json.field.value, user.account.collective) ) - resp <- Ok(Conversions.basicResult(res)) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value)) } yield resp case req @ POST -> Root / "customfieldremove" => @@ -216,7 +227,9 @@ object ItemMultiRoutes extends MultiIdSupport { res <- backend.customFields.deleteValue( RemoveValue(field, items, user.account.collective) ) - resp <- Ok(Conversions.basicResult(res, "Custom fields removed.")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Custom fields removed.")) } yield resp case req @ POST -> Root / "merge" => diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala index 5db15101..a2ff4ff9 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/ItemRoutes.scala @@ -25,6 +25,7 @@ import docspell.restapi.model._ import docspell.restserver.Config import docspell.restserver.conv.Conversions import docspell.restserver.http4s.BinaryUtil +import docspell.restserver.http4s.ClientRequestInfo import docspell.restserver.http4s.Responses import docspell.restserver.http4s.{QueryParam => QP} @@ -160,29 +161,37 @@ object ItemRoutes { for { tags <- req.as[StringList].map(_.items) res <- backend.item.setTags(id, tags, user.account.collective) - resp <- Ok(Conversions.basicResult(res, "Tags updated")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tags updated")) } yield resp case req @ POST -> Root / Ident(id) / "tags" => for { data <- req.as[Tag] rtag <- Conversions.newTag(data, user.account.collective) - res <- backend.item.addNewTag(id, rtag) - resp <- Ok(Conversions.basicResult(res, "Tag added.")) + res <- backend.item.addNewTag(user.account.collective, id, rtag) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tag added.")) } yield resp case req @ PUT -> Root / Ident(id) / "taglink" => for { tags <- req.as[StringList] res <- backend.item.linkTags(id, tags.items, user.account.collective) - resp <- Ok(Conversions.basicResult(res, "Tags linked")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tags linked")) } yield resp case req @ POST -> Root / Ident(id) / "tagtoggle" => for { tags <- req.as[StringList] res <- backend.item.toggleTags(id, tags.items, user.account.collective) - resp <- Ok(Conversions.basicResult(res, "Tags linked")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tags linked")) } yield resp case req @ POST -> Root / Ident(id) / "tagsremove" => @@ -193,7 +202,9 @@ object ItemRoutes { json.items, user.account.collective ) - resp <- Ok(Conversions.basicResult(res, "Tags removed")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Tags removed")) } yield resp case req @ PUT -> Root / Ident(id) / "direction" => @@ -392,15 +403,19 @@ object ItemRoutes { id, SetValue(data.field, data.value, user.account.collective) ) - resp <- Ok(Conversions.basicResult(res)) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value)) } yield resp - case DELETE -> Root / Ident(id) / "customfield" / Ident(fieldId) => + case req @ DELETE -> Root / Ident(id) / "customfield" / Ident(fieldId) => for { res <- backend.customFields.deleteValue( RemoveValue(fieldId, NonEmptyList.of(id), user.account.collective) ) - resp <- Ok(Conversions.basicResult(res, "Custom field value removed.")) + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + _ <- backend.notification.offerEvents(res.event(user.account, baseUrl.some)) + resp <- Ok(Conversions.basicResult(res.value, "Custom field value removed.")) } yield resp case DELETE -> Root / Ident(id) => diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala new file mode 100644 index 00000000..c462009e --- /dev/null +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/NotificationRoutes.scala @@ -0,0 +1,207 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restserver.routes + +import cats.effect._ +import cats.implicits._ + +import docspell.backend.BackendApp +import docspell.backend.auth.AuthToken +import docspell.common._ +import docspell.joexapi.model.BasicResult +import docspell.jsonminiq.JsonMiniQuery +import docspell.notification.api.EventType +import docspell.restapi.model._ +import docspell.restserver.Config +import docspell.restserver.conv.Conversions +import docspell.restserver.http4s.ClientRequestInfo + +import org.http4s._ +import org.http4s.circe.CirceEntityDecoder._ +import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.dsl.Http4sDsl +import org.http4s.server.Router + +object NotificationRoutes { + + def apply[F[_]: Async]( + cfg: Config, + backend: BackendApp[F], + user: AuthToken + ): HttpRoutes[F] = + Router( + "channel" -> channels(backend, user), + "hook" -> hooks(cfg, backend, user), + "event" -> events(cfg, backend, user) + ) + + def channels[F[_]: Async]( + backend: BackendApp[F], + user: AuthToken + ): HttpRoutes[F] = { + val dsl = new Http4sDsl[F] {} + import dsl._ + + HttpRoutes.of { + case GET -> Root => + for { + list <- backend.notification.listChannels(user.account) + data = list.map(NotificationChannel.convert) + resp <- Ok(data) + } yield resp + + case DELETE -> Root / Ident(id) => + for { + res <- backend.notification.deleteChannel(id, user.account) + resp <- Ok(Conversions.basicResult(res, "Channel deleted")) + } yield resp + + case req @ POST -> Root => + for { + input <- req.as[NotificationChannel] + ch <- Sync[F].pure(NotificationChannel.convert(input)).rethrow + res <- backend.notification.createChannel(ch, user.account) + resp <- Ok(Conversions.basicResult(res, "Channel created")) + } yield resp + + case req @ PUT -> Root => + for { + input <- req.as[NotificationChannel] + ch <- Sync[F].pure(NotificationChannel.convert(input)).rethrow + res <- backend.notification.updateChannel(ch, user.account) + resp <- Ok(Conversions.basicResult(res, "Channel created")) + } yield resp + } + } + + def hooks[F[_]: Async]( + cfg: Config, + backend: BackendApp[F], + user: AuthToken + ): HttpRoutes[F] = { + val dsl = new Http4sDsl[F] {} + import dsl._ + + HttpRoutes.of { + case GET -> Root => + for { + list <- backend.notification.listHooks(user.account) + data = list.map(Converters.convertHook) + resp <- Ok(data) + } yield resp + + case DELETE -> Root / Ident(id) => + for { + res <- backend.notification.deleteHook(id, user.account) + resp <- Ok(Conversions.basicResult(res, "Hook deleted.")) + } yield resp + + case req @ POST -> Root => + for { + input <- req.as[NotificationHook] + hook <- Sync[F].pure(Converters.convertHook(input)).rethrow + res <- backend.notification.createHook(hook, user.account) + resp <- Ok(Conversions.basicResult(res, "Hook created")) + } yield resp + + case req @ PUT -> Root => + for { + input <- req.as[NotificationHook] + hook <- Sync[F].pure(Converters.convertHook(input)).rethrow + res <- backend.notification.updateHook(hook, user.account) + resp <- Ok(Conversions.basicResult(res, "Hook updated")) + } yield resp + + case req @ POST -> Root / "verifyJsonFilter" => + for { + input <- req.as[StringValue] + res = JsonMiniQuery.parse(input.value) + resp <- Ok(BasicResult(res.isRight, res.fold(identity, _.unsafeAsString))) + } yield resp + + case req @ POST -> Root / "sendTestEvent" => + for { + input <- req.as[NotificationHook] + ch <- Sync[F] + .pure( + input.channel.left + .map(_ => new Exception(s"ChannelRefs not allowed for testing")) + .flatMap(NotificationChannel.convert) + ) + .rethrow + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + res <- backend.notification.sendSampleEvent( + input.events.headOption.getOrElse(EventType.all.head), + ch, + user.account, + baseUrl.some + ) + resp <- Ok(NotificationChannelTestResult(res.success, res.logMessages.toList)) + } yield resp + } + } + + def events[F[_]: Async]( + cfg: Config, + backend: BackendApp[F], + user: AuthToken + ): HttpRoutes[F] = { + val dsl = new Http4sDsl[F] {} + import dsl._ + + HttpRoutes.of { case req @ POST -> Root / "sample" => + for { + input <- req.as[NotificationSampleEventReq] + baseUrl = ClientRequestInfo.getBaseUrl(cfg, req) + data <- backend.notification.sampleEvent( + input.eventType, + user.account, + baseUrl.some + ) + resp <- Ok(data.asJsonWithMessage) + } yield resp + } + } + + object Converters { + + import docspell.backend.ops.ONotification + + def convertHook(h: ONotification.Hook): NotificationHook = + NotificationHook( + h.id, + h.enabled, + h.channel.map(NotificationChannel.convert), + h.allEvents, + h.eventFilter, + h.events + ) + + def convertHook(h: NotificationHook): Either[Throwable, ONotification.Hook] = + h.channel match { + case Left(cref) => + Right( + ONotification.Hook( + h.id, + h.enabled, + Left(cref), + h.allEvents, + h.eventFilter, + h.events + ) + ) + case Right(channel) => + NotificationChannel + .convert(channel) + .map(ch => + ONotification + .Hook(h.id, h.enabled, Right(ch), h.allEvents, h.eventFilter, h.events) + ) + } + + } +} diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala index 6ccb2a65..7ae72706 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/NotifyDueItemsRoutes.scala @@ -11,8 +11,10 @@ import cats.effect._ import cats.implicits._ import docspell.backend.BackendApp +import docspell.backend.MailAddressCodec import docspell.backend.auth.AuthToken import docspell.common._ +import docspell.notification.api.PeriodicDueItemsArgs import docspell.restapi.model._ import docspell.restserver.Config import docspell.restserver.conv.Conversions @@ -24,7 +26,7 @@ import org.http4s.circe.CirceEntityDecoder._ import org.http4s.circe.CirceEntityEncoder._ import org.http4s.dsl.Http4sDsl -object NotifyDueItemsRoutes { +object NotifyDueItemsRoutes extends MailAddressCodec { def apply[F[_]: Async]( cfg: Config, @@ -39,13 +41,13 @@ object NotifyDueItemsRoutes { case GET -> Root / Ident(id) => (for { task <- ut.findNotifyDueItems(id, UserTaskScope(user.account)) - res <- OptionT.liftF(taskToSettings(user.account, backend, task)) + res <- OptionT.liftF(taskToSettings(backend, task)) resp <- OptionT.liftF(Ok(res)) } yield resp).getOrElseF(NotFound()) case req @ POST -> Root / "startonce" => for { - data <- req.as[NotificationSettings] + data <- req.as[PeriodicDueItemsSettings] newId <- Ident.randomId[F] task <- makeTask(newId, getBaseUrl(cfg, req), user.account, data) res <- @@ -65,7 +67,7 @@ object NotifyDueItemsRoutes { } yield resp case req @ PUT -> Root => - def run(data: NotificationSettings) = + def run(data: PeriodicDueItemsSettings) = for { task <- makeTask(data.id, getBaseUrl(cfg, req), user.account, data) res <- @@ -75,7 +77,7 @@ object NotifyDueItemsRoutes { resp <- Ok(res) } yield resp for { - data <- req.as[NotificationSettings] + data <- req.as[PeriodicDueItemsSettings] resp <- if (data.id.isEmpty) Ok(BasicResult(false, "Empty id is not allowed")) else run(data) @@ -83,7 +85,7 @@ object NotifyDueItemsRoutes { case req @ POST -> Root => for { - data <- req.as[NotificationSettings] + data <- req.as[PeriodicDueItemsSettings] newId <- Ident.randomId[F] task <- makeTask(newId, getBaseUrl(cfg, req), user.account, data) res <- @@ -95,10 +97,9 @@ object NotifyDueItemsRoutes { case GET -> Root => ut.getNotifyDueItems(UserTaskScope(user.account)) - .evalMap(task => taskToSettings(user.account, backend, task)) + .evalMap(task => taskToSettings(backend, task)) .compile .toVector - .map(v => NotificationSettingsList(v.toList)) .flatMap(Ok(_)) } } @@ -110,50 +111,49 @@ object NotifyDueItemsRoutes { id: Ident, baseUrl: LenientUri, user: AccountId, - settings: NotificationSettings - ): F[UserTask[NotifyDueItemsArgs]] = - Sync[F].pure( + settings: PeriodicDueItemsSettings + ): F[UserTask[PeriodicDueItemsArgs]] = + Sync[F].pure(NotificationChannel.convert(settings.channel)).rethrow.map { channel => UserTask( id, - NotifyDueItemsArgs.taskName, + PeriodicDueItemsArgs.taskName, settings.enabled, settings.schedule, settings.summary, - NotifyDueItemsArgs( + PeriodicDueItemsArgs( user, - settings.smtpConnection, - settings.recipients, - Some(baseUrl / "app" / "item"), + Right(channel), settings.remindDays, if (settings.capOverdue) Some(settings.remindDays) else None, settings.tagsInclude.map(_.id), - settings.tagsExclude.map(_.id) + settings.tagsExclude.map(_.id), + Some(baseUrl / "app" / "item") ) ) - ) + } def taskToSettings[F[_]: Sync]( - account: AccountId, backend: BackendApp[F], - task: UserTask[NotifyDueItemsArgs] - ): F[NotificationSettings] = + task: UserTask[PeriodicDueItemsArgs] + ): F[PeriodicDueItemsSettings] = for { tinc <- backend.tag.loadAll(task.args.tagsInclude) texc <- backend.tag.loadAll(task.args.tagsExclude) - conn <- - backend.mail - .getSmtpSettings(account, None) - .map( - _.find(_.name == task.args.smtpConnection) - .map(_.name) + + ch <- task.args.channel match { + case Right(c) => NotificationChannel.convert(c).pure[F] + case Left(ref) => + Sync[F].raiseError( + new IllegalStateException(s"ChannelRefs are not supported: $ref") ) - } yield NotificationSettings( + } + + } yield PeriodicDueItemsSettings( task.id, task.enabled, task.summary, - conn.getOrElse(Ident.unsafe("")), - task.args.recipients, + ch, task.timer, task.args.remindDays, task.args.daysBack.isDefined, diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala new file mode 100644 index 00000000..b55e59ad --- /dev/null +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/PeriodicQueryRoutes.scala @@ -0,0 +1,161 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.restserver.routes + +import cats.data.OptionT +import cats.effect._ +import cats.implicits._ + +import docspell.backend.BackendApp +import docspell.backend.MailAddressCodec +import docspell.backend.auth.AuthToken +import docspell.common._ +import docspell.notification.api.PeriodicQueryArgs +import docspell.query.ItemQueryParser +import docspell.restapi.model._ +import docspell.restserver.Config +import docspell.restserver.conv.Conversions +import docspell.restserver.http4s.ClientRequestInfo +import docspell.store.usertask._ + +import org.http4s._ +import org.http4s.circe.CirceEntityDecoder._ +import org.http4s.circe.CirceEntityEncoder._ +import org.http4s.dsl.Http4sDsl + +object PeriodicQueryRoutes extends MailAddressCodec { + + def apply[F[_]: Async]( + cfg: Config, + backend: BackendApp[F], + user: AuthToken + ): HttpRoutes[F] = { + val dsl = new Http4sDsl[F] {} + val ut = backend.userTask + import dsl._ + + HttpRoutes.of { + case GET -> Root / Ident(id) => + (for { + task <- ut.findPeriodicQuery(id, UserTaskScope(user.account)) + res <- OptionT.liftF(taskToSettings(task)) + resp <- OptionT.liftF(Ok(res)) + } yield resp).getOrElseF(NotFound()) + + case req @ POST -> Root / "startonce" => + for { + data <- req.as[PeriodicQuerySettings] + newId <- Ident.randomId[F] + task <- makeTask(newId, getBaseUrl(cfg, req), user.account, data) + res <- + ut.executeNow(UserTaskScope(user.account), None, task) + .attempt + .map(Conversions.basicResult(_, "Submitted successfully.")) + resp <- Ok(res) + } yield resp + + case DELETE -> Root / Ident(id) => + for { + res <- + ut.deleteTask(UserTaskScope(user.account), id) + .attempt + .map(Conversions.basicResult(_, "Deleted successfully")) + resp <- Ok(res) + } yield resp + + case req @ PUT -> Root => + def run(data: PeriodicQuerySettings) = + for { + task <- makeTask(data.id, getBaseUrl(cfg, req), user.account, data) + res <- + ut.submitPeriodicQuery(UserTaskScope(user.account), None, task) + .attempt + .map(Conversions.basicResult(_, "Saved successfully")) + resp <- Ok(res) + } yield resp + for { + data <- req.as[PeriodicQuerySettings] + resp <- + if (data.id.isEmpty) Ok(BasicResult(false, "Empty id is not allowed")) + else run(data) + } yield resp + + case req @ POST -> Root => + for { + data <- req.as[PeriodicQuerySettings] + newId <- Ident.randomId[F] + task <- makeTask(newId, getBaseUrl(cfg, req), user.account, data) + res <- + ut.submitPeriodicQuery(UserTaskScope(user.account), None, task) + .attempt + .map(Conversions.basicResult(_, "Saved successfully.")) + resp <- Ok(res) + } yield resp + + case GET -> Root => + ut.getPeriodicQuery(UserTaskScope(user.account)) + .evalMap(task => taskToSettings(task)) + .compile + .toVector + .flatMap(Ok(_)) + } + } + + private def getBaseUrl[F[_]](cfg: Config, req: Request[F]) = + ClientRequestInfo.getBaseUrl(cfg, req) + + def makeTask[F[_]: Sync]( + id: Ident, + baseUrl: LenientUri, + user: AccountId, + settings: PeriodicQuerySettings + ): F[UserTask[PeriodicQueryArgs]] = + Sync[F] + .pure(for { + ch <- NotificationChannel.convert(settings.channel) + qstr <- ItemQueryParser + .asString(settings.query.expr) + .left + .map(err => new IllegalArgumentException(s"Query not renderable: $err")) + } yield (ch, ItemQueryString(qstr))) + .rethrow + .map { case (channel, qstr) => + UserTask( + id, + PeriodicQueryArgs.taskName, + settings.enabled, + settings.schedule, + settings.summary, + PeriodicQueryArgs( + user, + Right(channel), + qstr, + Some(baseUrl / "app" / "item") + ) + ) + } + + def taskToSettings[F[_]: Sync]( + task: UserTask[PeriodicQueryArgs] + ): F[PeriodicQuerySettings] = + for { + ch <- task.args.channel match { + case Right(c) => NotificationChannel.convert(c).pure[F] + case Left(ref) => + Sync[F].raiseError( + new IllegalStateException(s"ChannelRefs are not supported: $ref") + ) + } + } yield PeriodicQuerySettings( + task.id, + task.summary, + task.enabled, + ch, + ItemQueryParser.parseUnsafe(task.args.query.query), + task.timer + ) +} diff --git a/modules/restserver/src/main/scala/docspell/restserver/ws/OutputEvent.scala b/modules/restserver/src/main/scala/docspell/restserver/ws/OutputEvent.scala index d04424b2..c7e57be4 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/ws/OutputEvent.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/ws/OutputEvent.scala @@ -57,7 +57,6 @@ object OutputEvent { private case class Msg[A](tag: String, content: A) private object Msg { - @scala.annotation.nowarn implicit def jsonEncoder[A: Encoder]: Encoder[Msg[A]] = deriveEncoder } diff --git a/modules/store/src/main/resources/db/migration/h2/V1.29.1__notification.sql b/modules/store/src/main/resources/db/migration/h2/V1.29.1__notification.sql new file mode 100644 index 00000000..c9807f4c --- /dev/null +++ b/modules/store/src/main/resources/db/migration/h2/V1.29.1__notification.sql @@ -0,0 +1,62 @@ +create table "notification_channel_mail" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "conn_id" varchar(254) not null, + "recipients" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade, + foreign key ("conn_id") references "useremail"("id") on delete cascade +); + +create table "notification_channel_gotify" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "url" varchar(254) not null, + "app_key" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade +); + +create table "notification_channel_matrix" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "home_server" varchar(254) not null, + "room_id" varchar(254) not null, + "access_token" varchar not null, + "message_type" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade +); + +create table "notification_channel_http" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "url" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade +); + +create table "notification_hook" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "enabled" boolean not null, + "channel_mail" varchar(254), + "channel_gotify" varchar(254), + "channel_matrix" varchar(254), + "channel_http" varchar(254), + "all_events" boolean not null, + "event_filter" varchar(500), + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade, + foreign key ("channel_mail") references "notification_channel_mail"("id") on delete cascade, + foreign key ("channel_gotify") references "notification_channel_gotify"("id") on delete cascade, + foreign key ("channel_matrix") references "notification_channel_matrix"("id") on delete cascade, + foreign key ("channel_http") references "notification_channel_http"("id") on delete cascade +); + +create table "notification_hook_event" ( + "id" varchar(254) not null primary key, + "hook_id" varchar(254) not null, + "event_type" varchar(254) not null, + foreign key ("hook_id") references "notification_hook"("id") on delete cascade +); diff --git a/modules/store/src/main/resources/db/migration/mariadb/V1.29.1__notification.sql b/modules/store/src/main/resources/db/migration/mariadb/V1.29.1__notification.sql new file mode 100644 index 00000000..65b31436 --- /dev/null +++ b/modules/store/src/main/resources/db/migration/mariadb/V1.29.1__notification.sql @@ -0,0 +1,62 @@ +create table `notification_channel_mail` ( + `id` varchar(254) not null primary key, + `uid` varchar(254) not null, + `conn_id` varchar(254) not null, + `recipients` varchar(254) not null, + `created` timestamp not null, + foreign key (`uid`) references `user_`(`uid`) on delete cascade, + foreign key (`conn_id`) references `useremail`(`id`) on delete cascade +); + +create table `notification_channel_gotify` ( + `id` varchar(254) not null primary key, + `uid` varchar(254) not null, + `url` varchar(254) not null, + `app_key` varchar(254) not null, + `created` timestamp not null, + foreign key (`uid`) references `user_`(`uid`) on delete cascade +); + +create table `notification_channel_matrix` ( + `id` varchar(254) not null primary key, + `uid` varchar(254) not null, + `home_server` varchar(254) not null, + `room_id` varchar(254) not null, + `access_token` text not null, + `message_type` varchar(254) not null, + `created` timestamp not null, + foreign key (`uid`) references `user_`(`uid`) on delete cascade +); + +create table `notification_channel_http` ( + `id` varchar(254) not null primary key, + `uid` varchar(254) not null, + `url` varchar(254) not null, + `created` timestamp not null, + foreign key (`uid`) references `user_`(`uid`) on delete cascade +); + +create table `notification_hook` ( + `id` varchar(254) not null primary key, + `uid` varchar(254) not null, + `enabled` boolean not null, + `channel_mail` varchar(254), + `channel_gotify` varchar(254), + `channel_matrix` varchar(254), + `channel_http` varchar(254), + `all_events` boolean not null, + `event_filter` varchar(500), + `created` timestamp not null, + foreign key (`uid`) references `user_`(`uid`) on delete cascade, + foreign key (`channel_mail`) references `notification_channel_mail`(`id`) on delete cascade, + foreign key (`channel_gotify`) references `notification_channel_gotify`(`id`) on delete cascade, + foreign key (`channel_matrix`) references `notification_channel_matrix`(`id`) on delete cascade, + foreign key (`channel_http`) references `notification_channel_http`(`id`) on delete cascade +); + +create table `notification_hook_event` ( + `id` varchar(254) not null primary key, + `hook_id` varchar(254) not null, + `event_type` varchar(254) not null, + foreign key (`hook_id`) references `notification_hook`(`id`) on delete cascade +); diff --git a/modules/store/src/main/resources/db/migration/postgresql/V1.29.1__notification.sql b/modules/store/src/main/resources/db/migration/postgresql/V1.29.1__notification.sql new file mode 100644 index 00000000..c9807f4c --- /dev/null +++ b/modules/store/src/main/resources/db/migration/postgresql/V1.29.1__notification.sql @@ -0,0 +1,62 @@ +create table "notification_channel_mail" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "conn_id" varchar(254) not null, + "recipients" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade, + foreign key ("conn_id") references "useremail"("id") on delete cascade +); + +create table "notification_channel_gotify" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "url" varchar(254) not null, + "app_key" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade +); + +create table "notification_channel_matrix" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "home_server" varchar(254) not null, + "room_id" varchar(254) not null, + "access_token" varchar not null, + "message_type" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade +); + +create table "notification_channel_http" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "url" varchar(254) not null, + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade +); + +create table "notification_hook" ( + "id" varchar(254) not null primary key, + "uid" varchar(254) not null, + "enabled" boolean not null, + "channel_mail" varchar(254), + "channel_gotify" varchar(254), + "channel_matrix" varchar(254), + "channel_http" varchar(254), + "all_events" boolean not null, + "event_filter" varchar(500), + "created" timestamp not null, + foreign key ("uid") references "user_"("uid") on delete cascade, + foreign key ("channel_mail") references "notification_channel_mail"("id") on delete cascade, + foreign key ("channel_gotify") references "notification_channel_gotify"("id") on delete cascade, + foreign key ("channel_matrix") references "notification_channel_matrix"("id") on delete cascade, + foreign key ("channel_http") references "notification_channel_http"("id") on delete cascade +); + +create table "notification_hook_event" ( + "id" varchar(254) not null primary key, + "hook_id" varchar(254) not null, + "event_type" varchar(254) not null, + foreign key ("hook_id") references "notification_hook"("id") on delete cascade +); diff --git a/modules/store/src/main/scala/db/migration/MigrationTasks.scala b/modules/store/src/main/scala/db/migration/MigrationTasks.scala new file mode 100644 index 00000000..bd3e0f7a --- /dev/null +++ b/modules/store/src/main/scala/db/migration/MigrationTasks.scala @@ -0,0 +1,87 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package db.migration + +import cats.data.NonEmptyList +import cats.effect.{IO, Sync} +import cats.implicits._ + +import docspell.common._ +import docspell.common.syntax.StringSyntax._ +import docspell.notification.api.Channel +import docspell.notification.api.PeriodicDueItemsArgs +import docspell.store.records.RPeriodicTask + +import doobie._ +import doobie.implicits._ +import doobie.util.transactor.Strategy +import emil.MailAddress +import emil.javamail.syntax._ +import io.circe.Encoder +import io.circe.syntax._ +import org.flywaydb.core.api.migration.Context + +trait MigrationTasks { + + def logger: org.log4s.Logger + + implicit val jsonEncoder: Encoder[MailAddress] = + Encoder.encodeString.contramap(_.asUnicodeString) + + def migrateDueItemTasks: ConnectionIO[Unit] = + for { + tasks <- RPeriodicTask.findByTask(NotifyDueItemsArgs.taskName) + _ <- Sync[ConnectionIO].delay( + logger.info(s"Starting to migrate ${tasks.size} user tasks") + ) + _ <- tasks.traverse(migrateDueItemTask1) + _ <- RPeriodicTask.setEnabledByTask(NotifyDueItemsArgs.taskName, false) + } yield () + + def migrateDueItemTask1(old: RPeriodicTask): ConnectionIO[Int] = { + val converted = old.args + .parseJsonAs[NotifyDueItemsArgs] + .leftMap(_.getMessage()) + .flatMap(convertArgs) + + converted match { + case Right(args) => + Sync[ConnectionIO].delay(logger.info(s"Converting user task: $old")) *> + RPeriodicTask.updateTask( + old.id, + PeriodicDueItemsArgs.taskName, + args.asJson.noSpaces + ) + + case Left(err) => + logger.error(s"Error converting user task: $old. $err") + 0.pure[ConnectionIO] + } + } + + def convertArgs(old: NotifyDueItemsArgs): Either[String, PeriodicDueItemsArgs] = + old.recipients + .traverse(MailAddress.parse) + .flatMap(l => NonEmptyList.fromList(l).toRight("No recipients provided")) + .map { rec => + PeriodicDueItemsArgs( + old.account, + Right(Channel.Mail(Ident.unsafe(""), old.smtpConnection, rec)), + old.remindDays, + old.daysBack, + old.tagsInclude, + old.tagsExclude, + old.itemDetailUrl + ) + } + + def mkTransactor(ctx: Context): Transactor[IO] = { + val xa = Transactor.fromConnection[IO](ctx.getConnection()) + Transactor.strategy.set(xa, Strategy.void) //transactions are handled by flyway + } + +} diff --git a/modules/store/src/main/scala/db/migration/h2/V1_29_2__MigrateNotifyTask.scala b/modules/store/src/main/scala/db/migration/h2/V1_29_2__MigrateNotifyTask.scala new file mode 100644 index 00000000..ef85e970 --- /dev/null +++ b/modules/store/src/main/scala/db/migration/h2/V1_29_2__MigrateNotifyTask.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package db.migration.h2 + +import cats.effect.unsafe.implicits._ + +import db.migration.MigrationTasks +import doobie.implicits._ +import org.flywaydb.core.api.migration.BaseJavaMigration +import org.flywaydb.core.api.migration.Context + +class V1_29_2__MigrateNotifyTask extends BaseJavaMigration with MigrationTasks { + val logger = org.log4s.getLogger + + override def migrate(ctx: Context): Unit = { + val xa = mkTransactor(ctx) + migrateDueItemTasks.transact(xa).unsafeRunSync() + } +} diff --git a/modules/store/src/main/scala/db/migration/mariadb/V1_29_2__MigrateNotifyTask.scala b/modules/store/src/main/scala/db/migration/mariadb/V1_29_2__MigrateNotifyTask.scala new file mode 100644 index 00000000..4908ff15 --- /dev/null +++ b/modules/store/src/main/scala/db/migration/mariadb/V1_29_2__MigrateNotifyTask.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package db.migration.mariadb + +import cats.effect.unsafe.implicits._ + +import db.migration.MigrationTasks +import doobie.implicits._ +import org.flywaydb.core.api.migration.BaseJavaMigration +import org.flywaydb.core.api.migration.Context + +class V1_29_2__MigrateNotifyTask extends BaseJavaMigration with MigrationTasks { + val logger = org.log4s.getLogger + + override def migrate(ctx: Context): Unit = { + val xa = mkTransactor(ctx) + migrateDueItemTasks.transact(xa).unsafeRunSync() + } +} diff --git a/modules/store/src/main/scala/db/migration/postgresql/V1_29_2__MigrateNotifyTask.scala b/modules/store/src/main/scala/db/migration/postgresql/V1_29_2__MigrateNotifyTask.scala new file mode 100644 index 00000000..119a71e4 --- /dev/null +++ b/modules/store/src/main/scala/db/migration/postgresql/V1_29_2__MigrateNotifyTask.scala @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package db.migration.postgresql + +import cats.effect.unsafe.implicits._ + +import db.migration.MigrationTasks +import doobie.implicits._ +import org.flywaydb.core.api.migration.BaseJavaMigration +import org.flywaydb.core.api.migration.Context + +class V1_29_2__MigrateNotifyTask extends BaseJavaMigration with MigrationTasks { + val logger = org.log4s.getLogger + + override def migrate(ctx: Context): Unit = { + val xa = mkTransactor(ctx) + migrateDueItemTasks.transact(xa).unsafeRunSync() + } +} diff --git a/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala b/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala index 4c94b1c2..2b76e98a 100644 --- a/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala +++ b/modules/store/src/main/scala/docspell/store/impl/DoobieMeta.scala @@ -11,6 +11,8 @@ import java.time.{Instant, LocalDate} import docspell.common._ import docspell.common.syntax.all._ +import docspell.jsonminiq.JsonMiniQuery +import docspell.notification.api.EventType import docspell.query.{ItemQuery, ItemQueryParser} import docspell.totp.Key @@ -148,6 +150,12 @@ trait DoobieMeta extends EmilDoobieMeta { Meta[String].timap(s => ItemQueryParser.parseUnsafe(s))(q => q.raw.getOrElse(ItemQueryParser.unsafeAsString(q.expr)) ) + + implicit val metaEventType: Meta[EventType] = + Meta[String].timap(EventType.unsafeFromString)(_.name) + + implicit val metaJsonMiniQuery: Meta[JsonMiniQuery] = + Meta[String].timap(JsonMiniQuery.unsafeParse)(_.unsafeAsString) } object DoobieMeta extends DoobieMeta { diff --git a/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala b/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala index d4e40bfa..e5ecaf16 100644 --- a/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala +++ b/modules/store/src/main/scala/docspell/store/migrate/FlywayMigrate.scala @@ -22,12 +22,12 @@ object FlywayMigrate { logger.info("Running db migrations...") val locations = jdbc.dbmsName match { case Some(dbtype) => - List(s"classpath:db/migration/$dbtype") + List(s"classpath:db/migration/$dbtype", "classpath:db/migration/common") case None => logger.warn( s"Cannot read database name from jdbc url: ${jdbc.url}. Go with H2" ) - List("classpath:db/h2") + List("classpath:db/migration/h2", "classpath:db/migration/common") } logger.info(s"Using migration locations: $locations") diff --git a/modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala b/modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala new file mode 100644 index 00000000..44501ee8 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala @@ -0,0 +1,44 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.queries + +import cats.data.{NonEmptyList, OptionT} +import cats.effect._ + +import docspell.notification.api.NotificationChannel +import docspell.store.records._ + +import doobie.ConnectionIO + +object ChannelMap { + + def readMail(r: RNotificationChannelMail): ConnectionIO[Vector[NotificationChannel]] = + (for { + em <- OptionT(RUserEmail.getById(r.connection)) + rec <- OptionT.fromOption[ConnectionIO](NonEmptyList.fromList(r.recipients)) + ch = NotificationChannel.Email(em.toMailConfig, em.mailFrom, rec) + } yield Vector(ch)).getOrElse(Vector.empty) + + def readGotify( + r: RNotificationChannelGotify + ): ConnectionIO[Vector[NotificationChannel]] = + pure(NotificationChannel.Gotify(r.url, r.appKey)) + + def readMatrix( + r: RNotificationChannelMatrix + ): ConnectionIO[Vector[NotificationChannel]] = + pure(NotificationChannel.Matrix(r.homeServer, r.roomId, r.accessToken, r.messageType)) + + def readHttp( + r: RNotificationChannelHttp + ): ConnectionIO[Vector[NotificationChannel]] = + pure(NotificationChannel.HttpPost(r.url, Map.empty)) + + private def pure[A](a: A): ConnectionIO[Vector[A]] = + Sync[ConnectionIO].pure(Vector(a)) + +} diff --git a/modules/store/src/main/scala/docspell/store/queries/QNotification.scala b/modules/store/src/main/scala/docspell/store/queries/QNotification.scala new file mode 100644 index 00000000..b76dbde7 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/queries/QNotification.scala @@ -0,0 +1,91 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.queries + +import cats.Monad +import cats.data.OptionT +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api._ +import docspell.store.qb.DSL._ +import docspell.store.qb.Select +import docspell.store.records._ + +import doobie._ + +object QNotification { + + private val hook = RNotificationHook.as("nh") + private val hevent = RNotificationHookEvent.as("ne") + private val user = RUser.as("u") + + def findChannelsForEvent(event: Event): ConnectionIO[Vector[HookChannel]] = + for { + hooks <- listHooks(event.account.collective, event.eventType) + chs <- hooks.traverse(readHookChannel) + } yield chs + + // -- + + final case class HookChannel( + hook: RNotificationHook, + channels: Vector[NotificationChannel] + ) + + def listHooks( + collective: Ident, + eventType: EventType + ): ConnectionIO[Vector[RNotificationHook]] = + run( + select(hook.all), + from(hook).leftJoin(hevent, hevent.hookId === hook.id), + hook.enabled === true && (hook.allEvents === true || hevent.eventType === eventType) && hook.uid + .in( + Select(select(user.uid), from(user), user.cid === collective) + ) + ).query[RNotificationHook].to[Vector] + + def readHookChannel( + hook: RNotificationHook + ): ConnectionIO[HookChannel] = + for { + c1 <- read(hook.channelMail)(RNotificationChannelMail.getById)( + ChannelMap.readMail + ) + c2 <- read(hook.channelGotify)(RNotificationChannelGotify.getById)( + ChannelMap.readGotify + ) + c3 <- read(hook.channelMatrix)(RNotificationChannelMatrix.getById)( + ChannelMap.readMatrix + ) + c4 <- read(hook.channelHttp)(RNotificationChannelHttp.getById)(ChannelMap.readHttp) + } yield HookChannel(hook, c1 ++ c2 ++ c3 ++ c4) + + def readChannel(ch: RNotificationChannel): ConnectionIO[Vector[NotificationChannel]] = + ch.fold( + ChannelMap.readMail, + ChannelMap.readGotify, + ChannelMap.readMatrix, + ChannelMap.readHttp + ) + + private def read[A, B](channel: Option[Ident])( + load: Ident => ConnectionIO[Option[A]] + )( + m: A => ConnectionIO[Vector[B]] + ): ConnectionIO[Vector[B]] = + channel match { + case Some(ch) => + (for { + a <- OptionT(load(ch)) + ch <- OptionT.liftF(m(a)) + } yield ch).getOrElse(Vector.empty) + case None => + Monad[ConnectionIO].pure(Vector.empty) + } +} diff --git a/modules/store/src/main/scala/docspell/store/records/RItem.scala b/modules/store/src/main/scala/docspell/store/records/RItem.scala index 6a6d9d68..17faebba 100644 --- a/modules/store/src/main/scala/docspell/store/records/RItem.scala +++ b/modules/store/src/main/scala/docspell/store/records/RItem.scala @@ -410,6 +410,14 @@ object RItem { def findByIdAndCollective(itemId: Ident, coll: Ident): ConnectionIO[Option[RItem]] = run(select(T.all), from(T), T.id === itemId && T.cid === coll).query[RItem].option + def findAllByIdAndCollective( + itemIds: NonEmptyList[Ident], + coll: Ident + ): ConnectionIO[Vector[RItem]] = + run(select(T.all), from(T), T.id.in(itemIds) && T.cid === coll) + .query[RItem] + .to[Vector] + def findById(itemId: Ident): ConnectionIO[Option[RItem]] = run(select(T.all), from(T), T.id === itemId).query[RItem].option diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala new file mode 100644 index 00000000..6b6b5c53 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannel.scala @@ -0,0 +1,148 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.records + +import cats.data.OptionT + +import docspell.common._ +import docspell.notification.api.ChannelRef +import docspell.notification.api.ChannelType + +import doobie._ + +sealed trait RNotificationChannel { + + def id: Ident + + def fold[A]( + f1: RNotificationChannelMail => A, + f2: RNotificationChannelGotify => A, + f3: RNotificationChannelMatrix => A, + f4: RNotificationChannelHttp => A + ): A + +} + +object RNotificationChannel { + + final case class Email(r: RNotificationChannelMail) extends RNotificationChannel { + + override def fold[A]( + f1: RNotificationChannelMail => A, + f2: RNotificationChannelGotify => A, + f3: RNotificationChannelMatrix => A, + f4: RNotificationChannelHttp => A + ): A = f1(r) + + val id = r.id + } + + final case class Gotify(r: RNotificationChannelGotify) extends RNotificationChannel { + override def fold[A]( + f1: RNotificationChannelMail => A, + f2: RNotificationChannelGotify => A, + f3: RNotificationChannelMatrix => A, + f4: RNotificationChannelHttp => A + ): A = f2(r) + + val id = r.id + } + + final case class Matrix(r: RNotificationChannelMatrix) extends RNotificationChannel { + override def fold[A]( + f1: RNotificationChannelMail => A, + f2: RNotificationChannelGotify => A, + f3: RNotificationChannelMatrix => A, + f4: RNotificationChannelHttp => A + ): A = f3(r) + + val id = r.id + } + + final case class Http(r: RNotificationChannelHttp) extends RNotificationChannel { + override def fold[A]( + f1: RNotificationChannelMail => A, + f2: RNotificationChannelGotify => A, + f3: RNotificationChannelMatrix => A, + f4: RNotificationChannelHttp => A + ): A = f4(r) + + val id = r.id + } + + def insert(r: RNotificationChannel): ConnectionIO[Int] = + r.fold( + RNotificationChannelMail.insert, + RNotificationChannelGotify.insert, + RNotificationChannelMatrix.insert, + RNotificationChannelHttp.insert + ) + + def update(r: RNotificationChannel): ConnectionIO[Int] = + r.fold( + RNotificationChannelMail.update, + RNotificationChannelGotify.update, + RNotificationChannelMatrix.update, + RNotificationChannelHttp.update + ) + + def getByAccount(account: AccountId): ConnectionIO[Vector[RNotificationChannel]] = + for { + mail <- RNotificationChannelMail.getByAccount(account) + gotify <- RNotificationChannelGotify.getByAccount(account) + matrix <- RNotificationChannelMatrix.getByAccount(account) + http <- RNotificationChannelHttp.getByAccount(account) + } yield mail.map(Email.apply) ++ gotify.map(Gotify.apply) ++ matrix.map( + Matrix.apply + ) ++ http.map(Http.apply) + + def getById(id: Ident): ConnectionIO[Vector[RNotificationChannel]] = + for { + mail <- RNotificationChannelMail.getById(id) + gotify <- RNotificationChannelGotify.getById(id) + matrix <- RNotificationChannelMatrix.getById(id) + http <- RNotificationChannelHttp.getById(id) + } yield mail.map(Email.apply).toVector ++ + gotify.map(Gotify.apply).toVector ++ + matrix.map(Matrix.apply).toVector ++ + http.map(Http.apply).toVector + + def getByRef(ref: ChannelRef): ConnectionIO[Option[RNotificationChannel]] = + ref.channelType match { + case ChannelType.Mail => + RNotificationChannelMail.getById(ref.id).map(_.map(Email.apply)) + case ChannelType.Matrix => + RNotificationChannelMatrix.getById(ref.id).map(_.map(Matrix.apply)) + case ChannelType.Gotify => + RNotificationChannelGotify.getById(ref.id).map(_.map(Gotify.apply)) + case ChannelType.Http => + RNotificationChannelHttp.getById(ref.id).map(_.map(Http.apply)) + } + + def getByHook(r: RNotificationHook): ConnectionIO[Vector[RNotificationChannel]] = { + def opt(id: Option[Ident]): OptionT[ConnectionIO, Ident] = + OptionT.fromOption(id) + + for { + mail <- opt(r.channelMail).flatMapF(RNotificationChannelMail.getById).value + gotify <- opt(r.channelGotify).flatMapF(RNotificationChannelGotify.getById).value + matrix <- opt(r.channelMatrix).flatMapF(RNotificationChannelMatrix.getById).value + http <- opt(r.channelHttp).flatMapF(RNotificationChannelHttp.getById).value + } yield mail.map(Email.apply).toVector ++ + gotify.map(Gotify.apply).toVector ++ + matrix.map(Matrix.apply).toVector ++ + http.map(Http.apply).toVector + } + + def deleteByAccount(id: Ident, account: AccountId): ConnectionIO[Int] = + for { + n1 <- RNotificationChannelMail.deleteByAccount(id, account) + n2 <- RNotificationChannelGotify.deleteByAccount(id, account) + n3 <- RNotificationChannelMatrix.deleteByAccount(id, account) + n4 <- RNotificationChannelHttp.deleteByAccount(id, account) + } yield n1 + n2 + n3 + n4 +} diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala new file mode 100644 index 00000000..115da0ed --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala @@ -0,0 +1,86 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.records + +import cats.data.NonEmptyList + +import docspell.common._ +import docspell.store.qb.DSL._ +import docspell.store.qb._ + +import doobie._ +import doobie.implicits._ + +final case class RNotificationChannelGotify( + id: Ident, + uid: Ident, + url: LenientUri, + appKey: Password, + created: Timestamp +) { + def vary: RNotificationChannel = + RNotificationChannel.Gotify(this) +} + +object RNotificationChannelGotify { + + final case class Table(alias: Option[String]) extends TableDef { + val tableName = "notification_channel_gotify" + + val id = Column[Ident]("id", this) + val uid = Column[Ident]("uid", this) + val url = Column[LenientUri]("url", this) + val appKey = Column[Password]("app_key", this) + val created = Column[Timestamp]("created", this) + + val all: NonEmptyList[Column[_]] = + NonEmptyList.of(id, uid, url, appKey, created) + } + + val T: Table = Table(None) + def as(alias: String): Table = + Table(Some(alias)) + + def getById(id: Ident): ConnectionIO[Option[RNotificationChannelGotify]] = + run(select(T.all), from(T), T.id === id).query[RNotificationChannelGotify].option + + def insert(r: RNotificationChannelGotify): ConnectionIO[Int] = + DML.insert(T, T.all, sql"${r.id},${r.uid},${r.url},${r.appKey},${r.created}") + + def update(r: RNotificationChannelGotify): ConnectionIO[Int] = + DML.update( + T, + T.id === r.id && T.uid === r.uid, + DML.set( + T.url.setTo(r.url), + T.appKey.setTo(r.appKey) + ) + ) + + def getByAccount( + account: AccountId + ): ConnectionIO[Vector[RNotificationChannelGotify]] = { + val user = RUser.as("u") + val gotify = as("c") + Select( + select(gotify.all), + from(gotify).innerJoin(user, user.uid === gotify.uid), + user.cid === account.collective && user.login === account.user + ).build.query[RNotificationChannelGotify].to[Vector] + } + + def deleteById(id: Ident): ConnectionIO[Int] = + DML.delete(T, T.id === id) + + def deleteByAccount(id: Ident, account: AccountId): ConnectionIO[Int] = { + val u = RUser.as("u") + DML.delete( + T, + T.id === id && T.uid.in(Select(select(u.uid), from(u), u.isAccount(account))) + ) + } +} diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala new file mode 100644 index 00000000..b02108c2 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelHttp.scala @@ -0,0 +1,75 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.records + +import cats.data.NonEmptyList + +import docspell.common._ +import docspell.store.qb.DSL._ +import docspell.store.qb._ + +import doobie._ +import doobie.implicits._ + +final case class RNotificationChannelHttp( + id: Ident, + uid: Ident, + url: LenientUri, + created: Timestamp +) { + def vary: RNotificationChannel = + RNotificationChannel.Http(this) +} + +object RNotificationChannelHttp { + + final case class Table(alias: Option[String]) extends TableDef { + val tableName = "notification_channel_http" + + val id = Column[Ident]("id", this) + val uid = Column[Ident]("uid", this) + val url = Column[LenientUri]("url", this) + val created = Column[Timestamp]("created", this) + + val all: NonEmptyList[Column[_]] = + NonEmptyList.of(id, uid, url, created) + } + + val T: Table = Table(None) + def as(alias: String): Table = + Table(Some(alias)) + + def getById(id: Ident): ConnectionIO[Option[RNotificationChannelHttp]] = + run(select(T.all), from(T), T.id === id).query[RNotificationChannelHttp].option + + def insert(r: RNotificationChannelHttp): ConnectionIO[Int] = + DML.insert(T, T.all, sql"${r.id},${r.uid},${r.url},${r.created}") + + def update(r: RNotificationChannelHttp): ConnectionIO[Int] = + DML.update(T, T.id === r.id && T.uid === r.uid, DML.set(T.url.setTo(r.url))) + + def getByAccount(account: AccountId): ConnectionIO[Vector[RNotificationChannelHttp]] = { + val user = RUser.as("u") + val http = as("c") + Select( + select(http.all), + from(http).innerJoin(user, user.uid === http.uid), + user.cid === account.collective && user.login === account.user + ).build.query[RNotificationChannelHttp].to[Vector] + } + + def deleteById(id: Ident): ConnectionIO[Int] = + DML.delete(T, T.id === id) + + def deleteByAccount(id: Ident, account: AccountId): ConnectionIO[Int] = { + val u = RUser.as("u") + DML.delete( + T, + T.id === id && T.uid.in(Select(select(u.uid), from(u), u.isAccount(account))) + ) + } +} diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala new file mode 100644 index 00000000..db26b458 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMail.scala @@ -0,0 +1,88 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.records + +import cats.data.NonEmptyList + +import docspell.common._ +import docspell.store.qb.DSL._ +import docspell.store.qb._ + +import doobie._ +import doobie.implicits._ +import emil.MailAddress + +final case class RNotificationChannelMail( + id: Ident, + uid: Ident, + connection: Ident, + recipients: List[MailAddress], + created: Timestamp +) { + def vary: RNotificationChannel = + RNotificationChannel.Email(this) +} + +object RNotificationChannelMail { + final case class Table(alias: Option[String]) extends TableDef { + + val tableName = "notification_channel_mail" + + val id = Column[Ident]("id", this) + val uid = Column[Ident]("uid", this) + val connection = Column[Ident]("conn_id", this) + val recipients = Column[List[MailAddress]]("recipients", this) + val created = Column[Timestamp]("created", this) + + val all: NonEmptyList[Column[_]] = + NonEmptyList.of(id, uid, connection, recipients, created) + } + + val T: Table = Table(None) + def as(alias: String): Table = Table(Some(alias)) + + def insert(r: RNotificationChannelMail): ConnectionIO[Int] = + DML.insert( + T, + T.all, + sql"${r.id},${r.uid},${r.connection},${r.recipients},${r.created}" + ) + + def update(r: RNotificationChannelMail): ConnectionIO[Int] = + DML.update( + T, + T.id === r.id && T.uid === r.uid, + DML.set( + T.connection.setTo(r.connection), + T.recipients.setTo(r.recipients.toList) + ) + ) + + def getById(id: Ident): ConnectionIO[Option[RNotificationChannelMail]] = + run(select(T.all), from(T), T.id === id).query[RNotificationChannelMail].option + + def getByAccount(account: AccountId): ConnectionIO[Vector[RNotificationChannelMail]] = { + val user = RUser.as("u") + val gotify = as("c") + Select( + select(gotify.all), + from(gotify).innerJoin(user, user.uid === gotify.uid), + user.cid === account.collective && user.login === account.user + ).build.query[RNotificationChannelMail].to[Vector] + } + + def deleteById(id: Ident): ConnectionIO[Int] = + DML.delete(T, T.id === id) + + def deleteByAccount(id: Ident, account: AccountId): ConnectionIO[Int] = { + val u = RUser.as("u") + DML.delete( + T, + T.id === id && T.uid.in(Select(select(u.uid), from(u), u.isAccount(account))) + ) + } +} diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala new file mode 100644 index 00000000..1ba94ba5 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelMatrix.scala @@ -0,0 +1,93 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.records + +import cats.data.NonEmptyList + +import docspell.common._ +import docspell.store.qb.DSL._ +import docspell.store.qb._ + +import doobie._ +import doobie.implicits._ + +final case class RNotificationChannelMatrix( + id: Ident, + uid: Ident, + homeServer: LenientUri, + roomId: String, + accessToken: Password, + messageType: String, + created: Timestamp +) { + def vary: RNotificationChannel = + RNotificationChannel.Matrix(this) +} + +object RNotificationChannelMatrix { + final case class Table(alias: Option[String]) extends TableDef { + val tableName = "notification_channel_matrix" + + val id = Column[Ident]("id", this) + val uid = Column[Ident]("uid", this) + val homeServer = Column[LenientUri]("home_server", this) + val roomId = Column[String]("room_id", this) + val accessToken = Column[Password]("access_token", this) + val messageType = Column[String]("message_type", this) + val created = Column[Timestamp]("created", this) + + val all: NonEmptyList[Column[_]] = + NonEmptyList.of(id, uid, homeServer, roomId, accessToken, messageType, created) + } + val T: Table = Table(None) + def as(alias: String): Table = Table(Some(alias)) + + def insert(r: RNotificationChannelMatrix): ConnectionIO[Int] = + DML.insert( + T, + T.all, + sql"${r.id},${r.uid},${r.homeServer},${r.roomId},${r.accessToken},${r.messageType},${r.created}" + ) + + def update(r: RNotificationChannelMatrix): ConnectionIO[Int] = + DML.update( + T, + T.id === r.id && T.uid === r.uid, + DML.set( + T.homeServer.setTo(r.homeServer), + T.roomId.setTo(r.roomId), + T.accessToken.setTo(r.accessToken), + T.messageType.setTo(r.messageType) + ) + ) + + def getById(id: Ident): ConnectionIO[Option[RNotificationChannelMatrix]] = + run(select(T.all), from(T), T.id === id).query[RNotificationChannelMatrix].option + + def getByAccount( + account: AccountId + ): ConnectionIO[Vector[RNotificationChannelMatrix]] = { + val user = RUser.as("u") + val gotify = as("c") + Select( + select(gotify.all), + from(gotify).innerJoin(user, user.uid === gotify.uid), + user.cid === account.collective && user.login === account.user + ).build.query[RNotificationChannelMatrix].to[Vector] + } + + def deleteById(id: Ident): ConnectionIO[Int] = + DML.delete(T, T.id === id) + + def deleteByAccount(id: Ident, account: AccountId): ConnectionIO[Int] = { + val u = RUser.as("u") + DML.delete( + T, + T.id === id && T.uid.in(Select(select(u.uid), from(u), u.isAccount(account))) + ) + } +} diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationHook.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationHook.scala new file mode 100644 index 00000000..50b21f1e --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationHook.scala @@ -0,0 +1,233 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.records + +import cats.data.NonEmptyList +import cats.implicits._ + +import docspell.common._ +import docspell.jsonminiq.JsonMiniQuery +import docspell.notification.api.EventType +import docspell.store.qb.DSL._ +import docspell.store.qb._ + +import doobie._ +import doobie.implicits._ + +final case class RNotificationHook( + id: Ident, + uid: Ident, + enabled: Boolean, + channelMail: Option[Ident], + channelGotify: Option[Ident], + channelMatrix: Option[Ident], + channelHttp: Option[Ident], + allEvents: Boolean, + eventFilter: Option[JsonMiniQuery], + created: Timestamp +) { + def channelId: Ident = + channelMail + .orElse(channelGotify) + .orElse(channelMatrix) + .orElse(channelHttp) + .getOrElse( + sys.error(s"Illegal internal state: notification hook has no channel: ${id.id}") + ) +} + +object RNotificationHook { + def mail( + id: Ident, + uid: Ident, + enabled: Boolean, + channelMail: Ident, + created: Timestamp + ): RNotificationHook = + RNotificationHook( + id, + uid, + enabled, + channelMail.some, + None, + None, + None, + false, + None, + created + ) + + def gotify( + id: Ident, + uid: Ident, + enabled: Boolean, + channelGotify: Ident, + created: Timestamp + ): RNotificationHook = + RNotificationHook( + id, + uid, + enabled, + None, + channelGotify.some, + None, + None, + false, + None, + created + ) + + def matrix( + id: Ident, + uid: Ident, + enabled: Boolean, + channelMatrix: Ident, + created: Timestamp + ): RNotificationHook = + RNotificationHook( + id, + uid, + enabled, + None, + None, + channelMatrix.some, + None, + false, + None, + created + ) + + def http( + id: Ident, + uid: Ident, + enabled: Boolean, + channelHttp: Ident, + created: Timestamp + ): RNotificationHook = + RNotificationHook( + id, + uid, + enabled, + None, + None, + None, + channelHttp.some, + false, + None, + created + ) + + final case class Table(alias: Option[String]) extends TableDef { + val tableName = "notification_hook" + + val id = Column[Ident]("id", this) + val uid = Column[Ident]("uid", this) + val enabled = Column[Boolean]("enabled", this) + val channelMail = Column[Ident]("channel_mail", this) + val channelGotify = Column[Ident]("channel_gotify", this) + val channelMatrix = Column[Ident]("channel_matrix", this) + val channelHttp = Column[Ident]("channel_http", this) + val allEvents = Column[Boolean]("all_events", this) + val eventFilter = Column[JsonMiniQuery]("event_filter", this) + val created = Column[Timestamp]("created", this) + + val all: NonEmptyList[Column[_]] = + NonEmptyList.of( + id, + uid, + enabled, + channelMail, + channelGotify, + channelMatrix, + channelHttp, + allEvents, + eventFilter, + created + ) + } + + val T: Table = Table(None) + def as(alias: String): Table = Table(Some(alias)) + + def insert(r: RNotificationHook): ConnectionIO[Int] = + DML.insert( + T, + T.all, + sql"${r.id},${r.uid},${r.enabled},${r.channelMail},${r.channelGotify},${r.channelMatrix},${r.channelHttp},${r.allEvents},${r.eventFilter},${r.created}" + ) + + def deleteByAccount(id: Ident, account: AccountId): ConnectionIO[Int] = { + val u = RUser.as("u") + DML.delete( + T, + T.id === id && T.uid.in(Select(select(u.uid), from(u), u.isAccount(account))) + ) + } + + def update(r: RNotificationHook): ConnectionIO[Int] = + DML.update( + T, + T.id === r.id && T.uid === r.uid, + DML.set( + T.enabled.setTo(r.enabled), + T.channelMail.setTo(r.channelMail), + T.channelGotify.setTo(r.channelGotify), + T.channelMatrix.setTo(r.channelMatrix), + T.channelHttp.setTo(r.channelHttp), + T.allEvents.setTo(r.allEvents), + T.eventFilter.setTo(r.eventFilter) + ) + ) + + def findByAccount(account: AccountId): ConnectionIO[Vector[RNotificationHook]] = + Select( + select(T.all), + from(T), + T.uid.in(Select(select(RUser.T.uid), from(RUser.T), RUser.T.isAccount(account))) + ).build.query[RNotificationHook].to[Vector] + + def getById(id: Ident, userId: Ident): ConnectionIO[Option[RNotificationHook]] = + Select( + select(T.all), + from(T), + T.id === id && T.uid === userId + ).build.query[RNotificationHook].option + + def findAllByAccount( + account: AccountId + ): ConnectionIO[Vector[(RNotificationHook, List[EventType])]] = { + val h = RNotificationHook.as("h") + val e = RNotificationHookEvent.as("e") + val userSelect = + Select(select(RUser.T.uid), from(RUser.T), RUser.T.isAccount(account)) + + val withEvents = Select( + select(h.all :+ e.eventType), + from(h).innerJoin(e, e.hookId === h.id), + h.uid.in(userSelect) + ).orderBy(h.id) + .build + .query[(RNotificationHook, EventType)] + .to[Vector] + .map(_.groupBy(_._1).view.mapValues(_.map(_._2).toList).toVector) + + val withoutEvents = + Select( + select(h.all), + from(h), + h.id.notIn(Select(select(e.hookId), from(e))) && h.uid.in(userSelect) + ).build + .query[RNotificationHook] + .to[Vector] + .map(list => list.map(h => (h, Nil: List[EventType]))) + + for { + sel1 <- withEvents + sel2 <- withoutEvents + } yield sel1 ++ sel2 + } +} diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationHookEvent.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationHookEvent.scala new file mode 100644 index 00000000..0ea3e6e1 --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationHookEvent.scala @@ -0,0 +1,69 @@ +/* + * Copyright 2020 Eike K. & Contributors + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package docspell.store.records + +import cats.data.NonEmptyList +import cats.implicits._ + +import docspell.common._ +import docspell.notification.api.EventType +import docspell.store.qb.DSL._ +import docspell.store.qb._ + +import doobie._ +import doobie.implicits._ + +final case class RNotificationHookEvent( + id: Ident, + hookId: Ident, + eventType: EventType +) + +object RNotificationHookEvent { + final case class Table(alias: Option[String]) extends TableDef { + val tableName = "notification_hook_event" + + val id = Column[Ident]("id", this) + val hookId = Column[Ident]("hook_id", this) + val eventType = Column[EventType]("event_type", this) + + val all: NonEmptyList[Column[_]] = + NonEmptyList.of( + id, + hookId, + eventType + ) + } + + val T: Table = Table(None) + def as(alias: String): Table = Table(Some(alias)) + + def insert(r: RNotificationHookEvent): ConnectionIO[Int] = + DML.insert( + T, + T.all, + sql"${r.id},${r.hookId},${r.eventType}" + ) + + def insertAll(hookId: Ident, events: List[EventType]): ConnectionIO[Int] = + events + .traverse(et => + Ident + .randomId[ConnectionIO] + .flatMap(id => insert(RNotificationHookEvent(id, hookId, et))) + ) + .map(_.sum) + + def updateAll(hookId: Ident, events: List[EventType]): ConnectionIO[Int] = + deleteByHook(hookId) *> insertAll(hookId, events) + + def deleteByHook(hookId: Ident): ConnectionIO[Int] = + DML.delete(T, T.hookId === hookId) + + def update(r: RNotificationHookEvent): ConnectionIO[Int] = + DML.update(T, T.id === r.id, DML.set(T.eventType.setTo(r.eventType))) +} diff --git a/modules/store/src/main/scala/docspell/store/records/RPeriodicTask.scala b/modules/store/src/main/scala/docspell/store/records/RPeriodicTask.scala index 9aa68306..d0e27f07 100644 --- a/modules/store/src/main/scala/docspell/store/records/RPeriodicTask.scala +++ b/modules/store/src/main/scala/docspell/store/records/RPeriodicTask.scala @@ -164,6 +164,19 @@ object RPeriodicTask { def as(alias: String): Table = Table(Some(alias)) + def findByTask(taskName: Ident): ConnectionIO[Vector[RPeriodicTask]] = + Select( + select(T.all), + from(T), + T.task === taskName + ).build.query[RPeriodicTask].to[Vector] + + def updateTask(id: Ident, taskName: Ident, args: String): ConnectionIO[Int] = + DML.update(T, T.id === id, DML.set(T.task.setTo(taskName), T.args.setTo(args))) + + def setEnabledByTask(taskName: Ident, enabled: Boolean): ConnectionIO[Int] = + DML.update(T, T.task === taskName, DML.set(T.enabled.setTo(enabled))) + def insert(v: RPeriodicTask): ConnectionIO[Int] = DML.insert( T, diff --git a/modules/store/src/main/scala/docspell/store/records/RTagItem.scala b/modules/store/src/main/scala/docspell/store/records/RTagItem.scala index 38ac22dc..cb9467bd 100644 --- a/modules/store/src/main/scala/docspell/store/records/RTagItem.scala +++ b/modules/store/src/main/scala/docspell/store/records/RTagItem.scala @@ -95,11 +95,11 @@ object RTagItem { ) } yield n - def appendTags(item: Ident, tags: List[Ident]): ConnectionIO[Int] = + def appendTags(item: Ident, tags: List[Ident]): ConnectionIO[Set[Ident]] = for { existing <- findByItem(item) toadd = tags.toSet.diff(existing.map(_.tagId).toSet) - n <- setAllTags(item, toadd.toSeq) - } yield n + _ <- setAllTags(item, toadd.toSeq) + } yield toadd } diff --git a/modules/store/src/main/scala/docspell/store/records/RUser.scala b/modules/store/src/main/scala/docspell/store/records/RUser.scala index dbd4051c..af0c2224 100644 --- a/modules/store/src/main/scala/docspell/store/records/RUser.scala +++ b/modules/store/src/main/scala/docspell/store/records/RUser.scala @@ -71,6 +71,9 @@ object RUser { val lastLogin = Column[Timestamp]("lastlogin", this) val created = Column[Timestamp]("created", this) + def isAccount(aid: AccountId) = + cid === aid.collective && login === aid.user + val all = NonEmptyList.of[Column[_]]( uid, diff --git a/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala b/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala index 639c70b9..a11e330a 100644 --- a/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala +++ b/modules/store/src/main/scala/docspell/store/records/RUserEmail.scala @@ -176,6 +176,13 @@ object RUserEmail { run(select(t.all), from(t), t.uid === userId).query[RUserEmail].to[Vector] } + def getByUser(userId: Ident, name: Ident): ConnectionIO[Option[RUserEmail]] = { + val t = Table(None) + run(select(t.all), from(t), t.uid === userId && t.name === name) + .query[RUserEmail] + .option + } + private def findByAccount0( accId: AccountId, nameQ: Option[String], @@ -206,6 +213,11 @@ object RUserEmail { def getByName(accId: AccountId, name: Ident): ConnectionIO[Option[RUserEmail]] = findByAccount0(accId, Some(name.id), true).option + def getById(id: Ident): ConnectionIO[Option[RUserEmail]] = { + val t = Table(None) + run(select(t.all), from(t), t.id === id).query[RUserEmail].option + } + def delete(accId: AccountId, connName: Ident): ConnectionIO[Int] = { val user = RUser.as("u") diff --git a/modules/totp/src/main/scala/docspell/totp/Totp.scala b/modules/totp/src/main/scala/docspell/totp/Totp.scala index 7fe4c8c9..27b42812 100644 --- a/modules/totp/src/main/scala/docspell/totp/Totp.scala +++ b/modules/totp/src/main/scala/docspell/totp/Totp.scala @@ -49,9 +49,9 @@ object Totp { time.plus(generator.getTimeStep) ) - def checkPassword(key: Key, given: OnetimePassword, time: Instant): Boolean = { + def checkPassword(key: Key, givenPass: OnetimePassword, time: Instant): Boolean = { val pass = generate(key, time) - pass == given + pass == givenPass } } diff --git a/modules/webapp/elm.json b/modules/webapp/elm.json index b1071ec9..79183300 100644 --- a/modules/webapp/elm.json +++ b/modules/webapp/elm.json @@ -10,6 +10,7 @@ "CurrySoftware/elm-datepicker": "4.0.0", "NoRedInk/elm-json-decode-pipeline": "1.0.0", "NoRedInk/elm-simple-fuzzy": "1.0.3", + "ThinkAlexandria/elm-pretty-print-json": "1.0.1", "elm/browser": "1.0.2", "elm/core": "1.0.5", "elm/file": "1.0.5", @@ -35,9 +36,11 @@ "elm/parser": "1.1.0", "elm/regex": "1.0.0", "elm/virtual-dom": "1.0.2", + "elm-community/basics-extra": "4.1.0", "elm-community/list-extra": "8.2.4", "folkertdev/elm-flate": "2.0.4", - "justgook/elm-image": "4.0.0" + "justgook/elm-image": "4.0.0", + "the-sett/elm-pretty-printer": "2.2.3" } }, "test-dependencies": { diff --git a/modules/webapp/src/main/elm/Api.elm b/modules/webapp/src/main/elm/Api.elm index bb89794d..1d719f5c 100644 --- a/modules/webapp/src/main/elm/Api.elm +++ b/modules/webapp/src/main/elm/Api.elm @@ -21,10 +21,12 @@ module Api exposing , checkCalEvent , confirmMultiple , confirmOtp + , createHook , createImapSettings , createMailSettings , createNewFolder , createNotifyDueItems + , createPeriodicQuery , createScanMailbox , deleteAllItems , deleteAttachment @@ -34,11 +36,13 @@ module Api exposing , deleteCustomValueMultiple , deleteEquip , deleteFolder + , deleteHook , deleteImapSettings , deleteItem , deleteMailSettings , deleteNotifyDueItems , deleteOrg + , deletePeriodicQueryTask , deletePerson , deleteScanMailbox , deleteShare @@ -58,6 +62,7 @@ module Api exposing , getEquipments , getFolderDetail , getFolders + , getHooks , getImapSettings , getInsights , getItemProposals @@ -69,6 +74,7 @@ module Api exposing , getOrgLight , getOrganizations , getOtpState + , getPeriodicQuery , getPersonFull , getPersons , getPersonsLight @@ -113,6 +119,7 @@ module Api exposing , reprocessMultiple , restoreAllItems , restoreItem + , sampleEvent , saveClientSettings , searchShare , searchShareStats @@ -150,18 +157,24 @@ module Api exposing , startClassifier , startEmptyTrash , startOnceNotifyDueItems + , startOncePeriodicQuery , startOnceScanMailbox , startReIndex , submitNotifyDueItems + , submitPeriodicQuery + , testHook , toggleTags , twoFactor , unconfirmMultiple + , updateHook , updateNotifyDueItems + , updatePeriodicQuery , updateScanMailbox , updateShare , upload , uploadAmend , uploadSingle + , verifyJsonFilter , verifyShare , versionInfo ) @@ -208,8 +221,8 @@ import Api.Model.JobQueueState exposing (JobQueueState) import Api.Model.MoveAttachment exposing (MoveAttachment) import Api.Model.NewCustomField exposing (NewCustomField) import Api.Model.NewFolder exposing (NewFolder) -import Api.Model.NotificationSettings exposing (NotificationSettings) -import Api.Model.NotificationSettingsList exposing (NotificationSettingsList) +import Api.Model.NotificationChannelTestResult exposing (NotificationChannelTestResult) +import Api.Model.NotificationSampleEventReq exposing (NotificationSampleEventReq) import Api.Model.OptionalDate exposing (OptionalDate) import Api.Model.OptionalId exposing (OptionalId) import Api.Model.OptionalText exposing (OptionalText) @@ -239,6 +252,7 @@ import Api.Model.SourceAndTags exposing (SourceAndTags) import Api.Model.SourceList exposing (SourceList) import Api.Model.SourceTagIn import Api.Model.StringList exposing (StringList) +import Api.Model.StringValue exposing (StringValue) import Api.Model.Tag exposing (Tag) import Api.Model.TagCloud exposing (TagCloud) import Api.Model.TagList exposing (TagList) @@ -249,9 +263,13 @@ import Api.Model.VersionInfo exposing (VersionInfo) import Data.ContactType exposing (ContactType) import Data.CustomFieldOrder exposing (CustomFieldOrder) import Data.EquipmentOrder exposing (EquipmentOrder) +import Data.EventType exposing (EventType) import Data.Flags exposing (Flags) import Data.FolderOrder exposing (FolderOrder) +import Data.NotificationHook exposing (NotificationHook) import Data.OrganizationOrder exposing (OrganizationOrder) +import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings) +import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings) import Data.PersonOrder exposing (PersonOrder) import Data.Priority exposing (Priority) import Data.TagOrder exposing (TagOrder) @@ -571,68 +589,153 @@ deleteNotifyDueItems flags id receive = startOnceNotifyDueItems : Flags - -> NotificationSettings + -> PeriodicDueItemsSettings -> (Result Http.Error BasicResult -> msg) -> Cmd msg startOnceNotifyDueItems flags settings receive = Http2.authPost { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems/startonce" , account = getAccount flags - , body = Http.jsonBody (Api.Model.NotificationSettings.encode settings) + , body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings) , expect = Http.expectJson receive Api.Model.BasicResult.decoder } updateNotifyDueItems : Flags - -> NotificationSettings + -> PeriodicDueItemsSettings -> (Result Http.Error BasicResult -> msg) -> Cmd msg updateNotifyDueItems flags settings receive = Http2.authPut { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems" , account = getAccount flags - , body = Http.jsonBody (Api.Model.NotificationSettings.encode settings) + , body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings) , expect = Http.expectJson receive Api.Model.BasicResult.decoder } createNotifyDueItems : Flags - -> NotificationSettings + -> PeriodicDueItemsSettings -> (Result Http.Error BasicResult -> msg) -> Cmd msg createNotifyDueItems flags settings receive = Http2.authPost { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems" , account = getAccount flags - , body = Http.jsonBody (Api.Model.NotificationSettings.encode settings) + , body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings) , expect = Http.expectJson receive Api.Model.BasicResult.decoder } getNotifyDueItems : Flags - -> (Result Http.Error NotificationSettingsList -> msg) + -> (Result Http.Error (List PeriodicDueItemsSettings) -> msg) -> Cmd msg getNotifyDueItems flags receive = Http2.authGet { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems" , account = getAccount flags - , expect = Http.expectJson receive Api.Model.NotificationSettingsList.decoder + , expect = Http.expectJson receive (JsonDecode.list Data.PeriodicDueItemsSettings.decoder) } submitNotifyDueItems : Flags - -> NotificationSettings + -> PeriodicDueItemsSettings -> (Result Http.Error BasicResult -> msg) -> Cmd msg submitNotifyDueItems flags settings receive = Http2.authPost { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/notifydueitems" , account = getAccount flags - , body = Http.jsonBody (Api.Model.NotificationSettings.encode settings) + , body = Http.jsonBody (Data.PeriodicDueItemsSettings.encode settings) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + + +--- PeriodicQueryTask + + +deletePeriodicQueryTask : + Flags + -> String + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +deletePeriodicQueryTask flags id receive = + Http2.authDelete + { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery/" ++ id + , account = getAccount flags + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +startOncePeriodicQuery : + Flags + -> PeriodicQuerySettings + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +startOncePeriodicQuery flags settings receive = + Http2.authPost + { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery/startonce" + , account = getAccount flags + , body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +updatePeriodicQuery : + Flags + -> PeriodicQuerySettings + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +updatePeriodicQuery flags settings receive = + Http2.authPut + { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery" + , account = getAccount flags + , body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +createPeriodicQuery : + Flags + -> PeriodicQuerySettings + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +createPeriodicQuery flags settings receive = + Http2.authPost + { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery" + , account = getAccount flags + , body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +getPeriodicQuery : + Flags + -> (Result Http.Error (List PeriodicQuerySettings) -> msg) + -> Cmd msg +getPeriodicQuery flags receive = + Http2.authGet + { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery" + , account = getAccount flags + , expect = Http.expectJson receive (JsonDecode.list Data.PeriodicQuerySettings.decoder) + } + + +submitPeriodicQuery : + Flags + -> PeriodicQuerySettings + -> (Result Http.Error BasicResult -> msg) + -> Cmd msg +submitPeriodicQuery flags settings receive = + Http2.authPost + { url = flags.config.baseUrl ++ "/api/v1/sec/usertask/periodicquery" + , account = getAccount flags + , body = Http.jsonBody (Data.PeriodicQuerySettings.encode settings) , expect = Http.expectJson receive Api.Model.BasicResult.decoder } @@ -2353,6 +2456,88 @@ shareFileURL attachId = +--- NotificationHook + + +getHooks : Flags -> (Result Http.Error (List NotificationHook) -> msg) -> Cmd msg +getHooks flags receive = + Http2.authGet + { url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook" + , account = getAccount flags + , expect = Http.expectJson receive (JsonDecode.list Data.NotificationHook.decoder) + } + + +deleteHook : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg +deleteHook flags id receive = + Http2.authDelete + { url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook/" ++ id + , account = getAccount flags + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +createHook : Flags -> NotificationHook -> (Result Http.Error BasicResult -> msg) -> Cmd msg +createHook flags hook receive = + Http2.authPost + { url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook" + , account = getAccount flags + , body = Http.jsonBody (Data.NotificationHook.encode hook) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +updateHook : Flags -> NotificationHook -> (Result Http.Error BasicResult -> msg) -> Cmd msg +updateHook flags hook receive = + Http2.authPut + { url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook" + , account = getAccount flags + , body = Http.jsonBody (Data.NotificationHook.encode hook) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + +sampleEvent : Flags -> EventType -> (Result Http.Error String -> msg) -> Cmd msg +sampleEvent flags evt receive = + Http2.authPost + { url = flags.config.baseUrl ++ "/api/v1/sec/notification/event/sample" + , account = getAccount flags + , body = + Http.jsonBody + (Api.Model.NotificationSampleEventReq.encode + (NotificationSampleEventReq <| + Data.EventType.asString evt + ) + ) + , expect = Http.expectString receive + } + + +testHook : + Flags + -> NotificationHook + -> (Result Http.Error NotificationChannelTestResult -> msg) + -> Cmd msg +testHook flags hook receive = + Http2.authPost + { url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook/sendTestEvent" + , account = getAccount flags + , body = Http.jsonBody (Data.NotificationHook.encode hook) + , expect = Http.expectJson receive Api.Model.NotificationChannelTestResult.decoder + } + + +verifyJsonFilter : Flags -> String -> (Result Http.Error BasicResult -> msg) -> Cmd msg +verifyJsonFilter flags query receive = + Http2.authPost + { url = flags.config.baseUrl ++ "/api/v1/sec/notification/hook/verifyJsonFilter" + , account = getAccount flags + , body = Http.jsonBody (Api.Model.StringValue.encode (StringValue query)) + , expect = Http.expectJson receive Api.Model.BasicResult.decoder + } + + + --- Helper diff --git a/modules/webapp/src/main/elm/Comp/ChannelForm.elm b/modules/webapp/src/main/elm/Comp/ChannelForm.elm new file mode 100644 index 00000000..203fca16 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/ChannelForm.elm @@ -0,0 +1,280 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.ChannelForm exposing (..) + +import Api.Model.NotificationGotify exposing (NotificationGotify) +import Api.Model.NotificationHttp exposing (NotificationHttp) +import Api.Model.NotificationMail exposing (NotificationMail) +import Api.Model.NotificationMatrix exposing (NotificationMatrix) +import Comp.NotificationGotifyForm +import Comp.NotificationHttpForm +import Comp.NotificationMailForm +import Comp.NotificationMatrixForm +import Data.ChannelType exposing (ChannelType) +import Data.Flags exposing (Flags) +import Data.NotificationChannel exposing (NotificationChannel) +import Data.UiSettings exposing (UiSettings) +import Html exposing (..) +import Html.Attributes exposing (..) +import Messages.Comp.ChannelForm exposing (Texts) + + +type alias MatrixModel = + { form : Comp.NotificationMatrixForm.Model + , value : Maybe NotificationMatrix + } + + +type alias GotifyModel = + { form : Comp.NotificationGotifyForm.Model + , value : Maybe NotificationGotify + } + + +type alias MailModel = + { form : Comp.NotificationMailForm.Model + , value : Maybe NotificationMail + } + + +type alias HttpModel = + { form : Comp.NotificationHttpForm.Model + , value : Maybe NotificationHttp + } + + +type alias RefModel = + { channelType : ChannelType + } + + +type Model + = Matrix MatrixModel + | Gotify GotifyModel + | Mail MailModel + | Http HttpModel + | Ref RefModel + + +type Msg + = MatrixMsg Comp.NotificationMatrixForm.Msg + | GotifyMsg Comp.NotificationGotifyForm.Msg + | MailMsg Comp.NotificationMailForm.Msg + | HttpMsg Comp.NotificationHttpForm.Msg + + +init : Flags -> ChannelType -> ( Model, Cmd Msg ) +init flags ct = + case ct of + Data.ChannelType.Matrix -> + ( Matrix + { form = Comp.NotificationMatrixForm.init + , value = Nothing + } + , Cmd.none + ) + + Data.ChannelType.Gotify -> + ( Gotify + { form = Comp.NotificationGotifyForm.init + , value = Nothing + } + , Cmd.none + ) + + Data.ChannelType.Mail -> + let + ( mm, mc ) = + Comp.NotificationMailForm.init flags + in + ( Mail + { form = mm + , value = Nothing + } + , Cmd.map MailMsg mc + ) + + Data.ChannelType.Http -> + ( Http + { form = Comp.NotificationHttpForm.init + , value = Nothing + } + , Cmd.none + ) + + +initWith : Flags -> NotificationChannel -> ( Model, Cmd Msg ) +initWith flags channel = + case channel of + Data.NotificationChannel.Matrix m -> + ( Matrix + { form = Comp.NotificationMatrixForm.initWith m + , value = Just m + } + , Cmd.none + ) + + Data.NotificationChannel.Gotify m -> + ( Gotify + { form = Comp.NotificationGotifyForm.initWith m + , value = Just m + } + , Cmd.none + ) + + Data.NotificationChannel.Mail m -> + let + ( mm, mc ) = + Comp.NotificationMailForm.initWith flags m + in + ( Mail + { form = mm + , value = Just m + } + , Cmd.map MailMsg mc + ) + + Data.NotificationChannel.Http m -> + ( Http + { form = Comp.NotificationHttpForm.initWith m + , value = Just m + } + , Cmd.none + ) + + Data.NotificationChannel.Ref m -> + ( Ref { channelType = m.channelType } + , Cmd.none + ) + + +channelType : Model -> ChannelType +channelType model = + case model of + Matrix _ -> + Data.ChannelType.Matrix + + Gotify _ -> + Data.ChannelType.Gotify + + Mail _ -> + Data.ChannelType.Mail + + Http _ -> + Data.ChannelType.Http + + Ref ref -> + ref.channelType + + +getChannel : Model -> Maybe NotificationChannel +getChannel model = + case model of + Matrix mm -> + Maybe.map Data.NotificationChannel.Matrix mm.value + + Gotify mm -> + Maybe.map Data.NotificationChannel.Gotify mm.value + + Mail mm -> + Maybe.map Data.NotificationChannel.Mail mm.value + + Http mm -> + Maybe.map Data.NotificationChannel.Http mm.value + + Ref _ -> + Nothing + + + +--- Update + + +update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) +update flags msg model = + case msg of + MatrixMsg lm -> + case model of + Matrix matrix -> + let + ( mm, mv ) = + Comp.NotificationMatrixForm.update lm matrix.form + in + ( Matrix { form = mm, value = mv }, Cmd.none ) + + _ -> + ( model, Cmd.none ) + + GotifyMsg lm -> + case model of + Gotify gotify -> + let + ( mm, mv ) = + Comp.NotificationGotifyForm.update lm gotify.form + in + ( Gotify { form = mm, value = mv }, Cmd.none ) + + _ -> + ( model, Cmd.none ) + + MailMsg lm -> + case model of + Mail mail -> + let + ( mm, mc, mv ) = + Comp.NotificationMailForm.update flags lm mail.form + in + ( Mail { form = mm, value = mv }, Cmd.map MailMsg mc ) + + _ -> + ( model, Cmd.none ) + + HttpMsg lm -> + case model of + Http http -> + let + ( mm, mv ) = + Comp.NotificationHttpForm.update lm http.form + in + ( Http { form = mm, value = mv }, Cmd.none ) + + _ -> + ( model, Cmd.none ) + + + +--- View + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + case model of + Matrix m -> + Html.map MatrixMsg + (Comp.NotificationMatrixForm.view texts.matrixForm m.form) + + Gotify m -> + Html.map GotifyMsg + (Comp.NotificationGotifyForm.view texts.gotifyForm m.form) + + Mail m -> + Html.map MailMsg + (Comp.NotificationMailForm.view texts.mailForm settings m.form) + + Http m -> + Html.map HttpMsg + (Comp.NotificationHttpForm.view texts.httpForm m.form) + + -- Note: currently when retrieving hooks, this is not + -- send from the server. The server always sends + -- concrete channel details. However, it is possible + -- to create hooks with a reference to an existing + -- channel, but this is not supported in this client. + -- So this channel is ignored here. + Ref _ -> + span [ class "hidden" ] [] diff --git a/modules/webapp/src/main/elm/Comp/ChannelMenu.elm b/modules/webapp/src/main/elm/Comp/ChannelMenu.elm new file mode 100644 index 00000000..7c948d2d --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/ChannelMenu.elm @@ -0,0 +1,48 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.ChannelMenu exposing (..) + +import Comp.MenuBar as MB +import Data.ChannelType exposing (ChannelType) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick) +import Messages.Data.ChannelType exposing (Texts) +import Styles as S + + +type alias Model msg = + { menuOpen : Bool + , toggleMenu : msg + , menuLabel : String + , onItem : ChannelType -> msg + } + + +channelMenu : Texts -> Model msg -> MB.Item msg +channelMenu texts model = + MB.Dropdown + { linkIcon = "fa fa-plus" + , label = model.menuLabel + , linkClass = [ ( S.primaryButton, True ) ] + , toggleMenu = model.toggleMenu + , menuOpen = model.menuOpen + , items = + List.map (menuItem texts model) Data.ChannelType.all + } + + +menuItem : Texts -> Model msg -> ChannelType -> MB.DropdownMenu msg +menuItem texts model ct = + { icon = Data.ChannelType.icon ct "w-6 h-6 text-center inline-block" + , label = texts ct + , attrs = + [ href "" + , onClick (model.onItem ct) + ] + } diff --git a/modules/webapp/src/main/elm/Comp/Dropdown.elm b/modules/webapp/src/main/elm/Comp/Dropdown.elm index 417a92b0..75ce2fb3 100644 --- a/modules/webapp/src/main/elm/Comp/Dropdown.elm +++ b/modules/webapp/src/main/elm/Comp/Dropdown.elm @@ -14,6 +14,7 @@ module Comp.Dropdown exposing , isDropdownChangeMsg , makeModel , makeMultiple + , makeMultipleList , makeSingle , makeSingleList , mkOption @@ -116,6 +117,26 @@ makeMultiple = } +makeMultipleList : + { options : List a + , selected : List a + } + -> Model a +makeMultipleList opts = + let + m = + makeMultiple + + m2 = + { m | available = List.map (makeItem m) opts.options } + + m3 = + List.map (makeItem m2) opts.selected + |> List.foldl (\el -> \model -> selectItem model el) m2 + in + m3 + + getSelected : Model a -> List a getSelected model = List.map .value model.selected diff --git a/modules/webapp/src/main/elm/Comp/NotificationForm.elm b/modules/webapp/src/main/elm/Comp/DueItemsTaskForm.elm similarity index 74% rename from modules/webapp/src/main/elm/Comp/NotificationForm.elm rename to modules/webapp/src/main/elm/Comp/DueItemsTaskForm.elm index e3df64b9..a1fff82f 100644 --- a/modules/webapp/src/main/elm/Comp/NotificationForm.elm +++ b/modules/webapp/src/main/elm/Comp/DueItemsTaskForm.elm @@ -5,7 +5,7 @@ -} -module Comp.NotificationForm exposing +module Comp.DueItemsTaskForm exposing ( Action(..) , Model , Msg @@ -17,19 +17,21 @@ module Comp.NotificationForm exposing import Api import Api.Model.EmailSettingsList exposing (EmailSettingsList) -import Api.Model.NotificationSettings exposing (NotificationSettings) import Api.Model.Tag exposing (Tag) import Api.Model.TagList exposing (TagList) import Comp.Basic as B import Comp.CalEventInput +import Comp.ChannelForm import Comp.Dropdown -import Comp.EmailInput import Comp.IntField import Comp.MenuBar as MB import Comp.YesNoDimmer import Data.CalEvent exposing (CalEvent) +import Data.ChannelType exposing (ChannelType) import Data.DropdownStyle as DS import Data.Flags exposing (Flags) +import Data.NotificationChannel +import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings) import Data.TagOrder import Data.UiSettings exposing (UiSettings) import Data.Validated exposing (Validated(..)) @@ -38,7 +40,7 @@ import Html.Attributes exposing (..) import Html.Events exposing (onInput) import Http import Markdown -import Messages.Comp.NotificationForm exposing (Texts) +import Messages.Comp.DueItemsTaskForm exposing (Texts) import Styles as S import Util.Maybe import Util.Tag @@ -46,12 +48,10 @@ import Util.Update type alias Model = - { settings : NotificationSettings - , connectionModel : Comp.Dropdown.Model String + { settings : PeriodicDueItemsSettings + , channelModel : Comp.ChannelForm.Model , tagInclModel : Comp.Dropdown.Model Tag , tagExclModel : Comp.Dropdown.Model Tag - , recipients : List String - , recipientsModel : Comp.EmailInput.Model , remindDays : Maybe Int , remindDaysModel : Comp.IntField.Model , capOverdue : Bool @@ -72,15 +72,14 @@ type FormState type ValidateError - = ValidateConnectionMissing - | ValidateRemindDaysRequired - | ValidateRecipientsRequired + = ValidateRemindDaysRequired | ValidateCalEventInvalid + | ValidateChannelRequired type Action - = SubmitAction NotificationSettings - | StartOnceAction NotificationSettings + = SubmitAction PeriodicDueItemsSettings + | StartOnceAction PeriodicDueItemsSettings | CancelAction | DeleteAction String | NoAction @@ -90,9 +89,6 @@ type Msg = Submit | TagIncMsg (Comp.Dropdown.Msg Tag) | TagExcMsg (Comp.Dropdown.Msg Tag) - | ConnMsg (Comp.Dropdown.Msg String) - | ConnResp (Result Http.Error EmailSettingsList) - | RecipientMsg Comp.EmailInput.Msg | GetTagsResp (Result Http.Error TagList) | RemindDaysMsg Comp.IntField.Msg | ToggleEnabled @@ -103,26 +99,25 @@ type Msg | RequestDelete | YesNoDeleteMsg Comp.YesNoDimmer.Msg | SetSummary String + | ChannelMsg Comp.ChannelForm.Msg -initWith : Flags -> NotificationSettings -> ( Model, Cmd Msg ) +initWith : Flags -> PeriodicDueItemsSettings -> ( Model, Cmd Msg ) initWith flags s = let - ( im, ic ) = - init flags + ct = + Data.NotificationChannel.channelType s.channel + |> Maybe.withDefault Data.ChannelType.Matrix - smtp = - Util.Maybe.fromString s.smtpConnection - |> Maybe.map List.singleton - |> Maybe.withDefault [] + ( im, ic ) = + init flags ct removeAction ( tm, _, tc ) = ( tm, tc ) ( nm, nc ) = Util.Update.andThen1 - [ update flags (ConnMsg (Comp.Dropdown.SetSelection smtp)) >> removeAction - , update flags (TagIncMsg (Comp.Dropdown.SetSelection s.tagsInclude)) >> removeAction + [ update flags (TagIncMsg (Comp.Dropdown.SetSelection s.tagsInclude)) >> removeAction , update flags (TagExcMsg (Comp.Dropdown.SetSelection s.tagsExclude)) >> removeAction ] im @@ -133,10 +128,13 @@ initWith flags s = ( sm, sc ) = Comp.CalEventInput.init flags newSchedule + + ( cfm, cfc ) = + Comp.ChannelForm.initWith flags s.channel in ( { nm | settings = s - , recipients = s.recipients + , channelModel = cfm , remindDays = Just s.remindDays , enabled = s.enabled , capOverdue = s.capOverdue @@ -151,25 +149,27 @@ initWith flags s = [ nc , ic , Cmd.map CalEventMsg sc + , Cmd.map ChannelMsg cfc ] ) -init : Flags -> ( Model, Cmd Msg ) -init flags = +init : Flags -> ChannelType -> ( Model, Cmd Msg ) +init flags ct = let initialSchedule = Data.CalEvent.everyMonth ( sm, scmd ) = Comp.CalEventInput.init flags initialSchedule + + ( cfm, cfc ) = + Comp.ChannelForm.init flags ct in - ( { settings = Api.Model.NotificationSettings.empty - , connectionModel = Comp.Dropdown.makeSingle + ( { settings = Data.PeriodicDueItemsSettings.empty ct + , channelModel = cfm , tagInclModel = Util.Tag.makeDropdownModel , tagExclModel = Util.Tag.makeDropdownModel - , recipients = [] - , recipientsModel = Comp.EmailInput.init , remindDays = Just 1 , remindDaysModel = Comp.IntField.init (Just 1) Nothing True , enabled = False @@ -177,14 +177,14 @@ init flags = , schedule = Just initialSchedule , scheduleModel = sm , formState = FormStateInitial - , loading = 2 + , loading = 1 , yesNoDelete = Comp.YesNoDimmer.emptyModel , summary = Nothing } , Cmd.batch - [ Api.getMailSettings flags "" ConnResp - , Api.getTags flags "" Data.TagOrder.NameAsc GetTagsResp + [ Api.getTags flags "" Data.TagOrder.NameAsc GetTagsResp , Cmd.map CalEventMsg scmd + , Cmd.map ChannelMsg cfc ] ) @@ -193,25 +193,12 @@ init flags = --- Update -makeSettings : Model -> Result ValidateError NotificationSettings +makeSettings : Model -> Result ValidateError PeriodicDueItemsSettings makeSettings model = let prev = model.settings - conn = - Comp.Dropdown.getSelected model.connectionModel - |> List.head - |> Maybe.map Ok - |> Maybe.withDefault (Err ValidateConnectionMissing) - - recp = - if List.isEmpty model.recipients then - Err ValidateRecipientsRequired - - else - Ok model.recipients - rmdays = Maybe.map Ok model.remindDays |> Maybe.withDefault (Err ValidateRemindDaysRequired) @@ -224,27 +211,30 @@ makeSettings model = Nothing -> Err ValidateCalEventInvalid - make smtp rec days timer = + channelM = + Result.fromMaybe + ValidateChannelRequired + (Comp.ChannelForm.getChannel model.channelModel) + + make days timer channel = { prev - | smtpConnection = smtp - , tagsInclude = Comp.Dropdown.getSelected model.tagInclModel + | tagsInclude = Comp.Dropdown.getSelected model.tagInclModel , tagsExclude = Comp.Dropdown.getSelected model.tagExclModel - , recipients = rec , remindDays = days , capOverdue = model.capOverdue , enabled = model.enabled , schedule = Data.CalEvent.makeEvent timer , summary = model.summary + , channel = channel } in - Result.map4 make - conn - recp + Result.map3 make rmdays schedule_ + channelM -withValidSettings : (NotificationSettings -> Action) -> Model -> ( Model, Action, Cmd Msg ) +withValidSettings : (PeriodicDueItemsSettings -> Action) -> Model -> ( Model, Action, Cmd Msg ) withValidSettings mkcmd model = case makeSettings model of Ok set -> @@ -263,6 +253,16 @@ withValidSettings mkcmd model = update : Flags -> Msg -> Model -> ( Model, Action, Cmd Msg ) update flags msg model = case msg of + ChannelMsg lm -> + let + ( cfm, cfc ) = + Comp.ChannelForm.update flags lm model.channelModel + in + ( { model | channelModel = cfm } + , NoAction + , Cmd.map ChannelMsg cfc + ) + CalEventMsg lmsg -> let ( cm, cc, cs ) = @@ -280,67 +280,6 @@ update flags msg model = , Cmd.map CalEventMsg cc ) - RecipientMsg m -> - let - ( em, ec, rec ) = - Comp.EmailInput.update flags model.recipients m model.recipientsModel - in - ( { model - | recipients = rec - , recipientsModel = em - , formState = FormStateInitial - } - , NoAction - , Cmd.map RecipientMsg ec - ) - - ConnMsg m -> - let - ( cm, cc ) = - Comp.Dropdown.update m model.connectionModel - in - ( { model - | connectionModel = cm - , formState = FormStateInitial - } - , NoAction - , Cmd.map ConnMsg cc - ) - - ConnResp (Ok list) -> - let - names = - List.map .name list.items - - cm = - Comp.Dropdown.makeSingleList - { options = names - , selected = List.head names - } - in - ( { model - | connectionModel = cm - , loading = model.loading - 1 - , formState = - if names == [] then - FormStateInvalid ValidateConnectionMissing - - else - FormStateInitial - } - , NoAction - , Cmd.none - ) - - ConnResp (Err err) -> - ( { model - | formState = FormStateHttpError err - , loading = model.loading - 1 - } - , NoAction - , Cmd.none - ) - TagIncMsg m -> let ( m2, c2 ) = @@ -509,12 +448,10 @@ view2 texts extraClasses settings model = , icon = Just "fa fa-play" } - connectionCfg = - { makeOption = \a -> { text = a, additional = "" } - , placeholder = texts.selectConnection - , labelColor = \_ -> \_ -> "" - , style = DS.mainStyle - } + formHeader txt = + h2 [ class S.formHeader, class "mt-2" ] + [ text txt + ] in div [ class "flex flex-col md:relative" @@ -539,7 +476,7 @@ view2 texts extraClasses settings model = } , MB.SecondaryButton { tagger = Cancel - , label = texts.basics.cancel + , label = texts.basics.backToList , title = texts.basics.backToList , icon = Just "fa fa-arrow-left" } @@ -575,17 +512,14 @@ view2 texts extraClasses settings model = FormStateHttpError err -> text (texts.httpError err) - FormStateInvalid ValidateConnectionMissing -> - text texts.connectionMissing - FormStateInvalid ValidateCalEventInvalid -> text texts.invalidCalEvent FormStateInvalid ValidateRemindDaysRequired -> text texts.remindDaysRequired - FormStateInvalid ValidateRecipientsRequired -> - text texts.recipientsRequired + FormStateInvalid ValidateChannelRequired -> + text texts.channelRequired ] , div [ class "mb-4" ] [ MB.viewItem <| @@ -613,37 +547,11 @@ view2 texts extraClasses settings model = ] ] , div [ class "mb-4" ] - [ label [ class S.inputLabel ] - [ text texts.sendVia - , B.inputRequired - ] - , Html.map ConnMsg - (Comp.Dropdown.view2 - connectionCfg - settings - model.connectionModel - ) - , span [ class "opacity-50 text-sm" ] - [ text texts.sendViaInfo - ] - ] - , div [ class "mb-4" ] - [ label - [ class S.inputLabel - ] - [ text texts.recipients - , B.inputRequired - ] - , Html.map RecipientMsg - (Comp.EmailInput.view2 - { style = DS.mainStyle, placeholder = texts.recipients } - model.recipients - model.recipientsModel - ) - , span [ class "opacity-50 text-sm" ] - [ text texts.recipientsInfo - ] + [ formHeader (texts.channelHeader (Comp.ChannelForm.channelType model.channelModel)) + , Html.map ChannelMsg + (Comp.ChannelForm.view texts.channelForm settings model.channelModel) ] + , formHeader texts.queryLabel , div [ class "mb-4" ] [ label [ class S.inputLabel ] [ text texts.tagsInclude ] @@ -666,7 +574,7 @@ view2 texts extraClasses settings model = settings model.tagExclModel ) - , span [ class "small-info" ] + , span [ class "opacity-50 text-sm" ] [ text texts.tagsExcludeInfo ] ] @@ -692,7 +600,8 @@ view2 texts extraClasses settings model = ] ] , div [ class "mb-4" ] - [ label [ class S.inputLabel ] + [ formHeader texts.schedule + , label [ class S.inputLabel ] [ text texts.schedule , a [ class "float-right" diff --git a/modules/webapp/src/main/elm/Comp/NotificationList.elm b/modules/webapp/src/main/elm/Comp/DueItemsTaskList.elm similarity index 74% rename from modules/webapp/src/main/elm/Comp/NotificationList.elm rename to modules/webapp/src/main/elm/Comp/DueItemsTaskList.elm index 7d241303..565d00ba 100644 --- a/modules/webapp/src/main/elm/Comp/NotificationList.elm +++ b/modules/webapp/src/main/elm/Comp/DueItemsTaskList.elm @@ -5,7 +5,7 @@ -} -module Comp.NotificationList exposing +module Comp.DueItemsTaskList exposing ( Action(..) , Model , Msg @@ -14,11 +14,13 @@ module Comp.NotificationList exposing , view2 ) -import Api.Model.NotificationSettings exposing (NotificationSettings) import Comp.Basic as B +import Data.ChannelType +import Data.NotificationChannel +import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings) import Html exposing (..) import Html.Attributes exposing (..) -import Messages.Comp.NotificationTable exposing (Texts) +import Messages.Comp.DueItemsTaskList exposing (Texts) import Styles as S import Util.Html @@ -28,12 +30,12 @@ type alias Model = type Msg - = EditSettings NotificationSettings + = EditSettings PeriodicDueItemsSettings type Action = NoAction - | EditAction NotificationSettings + | EditAction PeriodicDueItemsSettings init : Model @@ -52,7 +54,7 @@ update msg model = --- View2 -view2 : Texts -> Model -> List NotificationSettings -> Html Msg +view2 : Texts -> Model -> List PeriodicDueItemsSettings -> Html Msg view2 texts _ items = div [] [ table [ class S.tableMain ] @@ -67,8 +69,6 @@ view2 texts _ items = [ text texts.schedule ] , th [ class "text-left mr-2" ] [ text texts.connection ] - , th [ class "text-left hidden sm:table-cell mr-2" ] - [ text texts.recipients ] ] ] , tbody [] @@ -77,7 +77,7 @@ view2 texts _ items = ] -viewItem2 : Texts -> NotificationSettings -> Html Msg +viewItem2 : Texts -> PeriodicDueItemsSettings -> Html Msg viewItem2 texts item = tr [] [ B.editLinkTableCell texts.basics.edit (EditSettings item) @@ -94,9 +94,9 @@ viewItem2 texts item = ] ] , td [ class "text-left mr-2" ] - [ text item.smtpConnection - ] - , td [ class "text-left hidden sm:table-cell mr-2" ] - [ String.join ", " item.recipients |> text + [ Data.NotificationChannel.channelType item.channel + |> Maybe.map Data.ChannelType.asString + |> Maybe.withDefault "-" + |> text ] ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationManage.elm b/modules/webapp/src/main/elm/Comp/DueItemsTaskManage.elm similarity index 75% rename from modules/webapp/src/main/elm/Comp/NotificationManage.elm rename to modules/webapp/src/main/elm/Comp/DueItemsTaskManage.elm index 2779f147..a84c8a0f 100644 --- a/modules/webapp/src/main/elm/Comp/NotificationManage.elm +++ b/modules/webapp/src/main/elm/Comp/DueItemsTaskManage.elm @@ -5,7 +5,7 @@ -} -module Comp.NotificationManage exposing +module Comp.DueItemsTaskManage exposing ( Model , Msg , init @@ -15,25 +15,27 @@ module Comp.NotificationManage exposing import Api import Api.Model.BasicResult exposing (BasicResult) -import Api.Model.NotificationSettings exposing (NotificationSettings) -import Api.Model.NotificationSettingsList exposing (NotificationSettingsList) +import Comp.ChannelMenu +import Comp.DueItemsTaskForm +import Comp.DueItemsTaskList import Comp.MenuBar as MB -import Comp.NotificationForm -import Comp.NotificationList +import Data.ChannelType exposing (ChannelType) import Data.Flags exposing (Flags) +import Data.PeriodicDueItemsSettings exposing (PeriodicDueItemsSettings) import Data.UiSettings exposing (UiSettings) import Html exposing (..) import Html.Attributes exposing (..) import Http -import Messages.Comp.NotificationManage exposing (Texts) +import Messages.Comp.DueItemsTaskManage exposing (Texts) import Styles as S type alias Model = - { listModel : Comp.NotificationList.Model - , detailModel : Maybe Comp.NotificationForm.Model - , items : List NotificationSettings + { listModel : Comp.DueItemsTaskList.Model + , detailModel : Maybe Comp.DueItemsTaskForm.Model + , items : List PeriodicDueItemsSettings , formState : FormState + , channelMenuOpen : Bool } @@ -52,19 +54,21 @@ type FormState type Msg - = ListMsg Comp.NotificationList.Msg - | DetailMsg Comp.NotificationForm.Msg - | GetDataResp (Result Http.Error NotificationSettingsList) - | NewTask + = ListMsg Comp.DueItemsTaskList.Msg + | DetailMsg Comp.DueItemsTaskForm.Msg + | GetDataResp (Result Http.Error (List PeriodicDueItemsSettings)) + | NewTaskInit ChannelType | SubmitResp SubmitType (Result Http.Error BasicResult) + | ToggleChannelMenu initModel : Model initModel = - { listModel = Comp.NotificationList.init + { listModel = Comp.DueItemsTaskList.init , detailModel = Nothing , items = [] , formState = FormStateInitial + , channelMenuOpen = False } @@ -85,9 +89,14 @@ init flags = update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) update flags msg model = case msg of - GetDataResp (Ok res) -> + ToggleChannelMenu -> + ( { model | channelMenuOpen = not model.channelMenuOpen } + , Cmd.none + ) + + GetDataResp (Ok items) -> ( { model - | items = res.items + | items = items , formState = FormStateInitial } , Cmd.none @@ -101,17 +110,17 @@ update flags msg model = ListMsg lm -> let ( mm, action ) = - Comp.NotificationList.update lm model.listModel + Comp.DueItemsTaskList.update lm model.listModel ( detail, cmd ) = case action of - Comp.NotificationList.NoAction -> + Comp.DueItemsTaskList.NoAction -> ( Nothing, Cmd.none ) - Comp.NotificationList.EditAction settings -> + Comp.DueItemsTaskList.EditAction settings -> let ( dm, dc ) = - Comp.NotificationForm.initWith flags settings + Comp.DueItemsTaskForm.initWith flags settings in ( Just dm, Cmd.map DetailMsg dc ) in @@ -127,11 +136,11 @@ update flags msg model = Just dm -> let ( mm, action, mc ) = - Comp.NotificationForm.update flags lm dm + Comp.DueItemsTaskForm.update flags lm dm ( model_, cmd_ ) = case action of - Comp.NotificationForm.NoAction -> + Comp.DueItemsTaskForm.NoAction -> ( { model | detailModel = Just mm , formState = FormStateInitial @@ -139,7 +148,7 @@ update flags msg model = , Cmd.none ) - Comp.NotificationForm.SubmitAction settings -> + Comp.DueItemsTaskForm.SubmitAction settings -> ( { model | detailModel = Just mm , formState = FormStateInitial @@ -151,7 +160,7 @@ update flags msg model = Api.updateNotifyDueItems flags settings (SubmitResp SubmitUpdate) ) - Comp.NotificationForm.CancelAction -> + Comp.DueItemsTaskForm.CancelAction -> ( { model | detailModel = Nothing , formState = FormStateInitial @@ -159,7 +168,7 @@ update flags msg model = , initCmd flags ) - Comp.NotificationForm.StartOnceAction settings -> + Comp.DueItemsTaskForm.StartOnceAction settings -> ( { model | detailModel = Just mm , formState = FormStateInitial @@ -167,7 +176,7 @@ update flags msg model = , Api.startOnceNotifyDueItems flags settings (SubmitResp SubmitStartOnce) ) - Comp.NotificationForm.DeleteAction id -> + Comp.DueItemsTaskForm.DeleteAction id -> ( { model | detailModel = Just mm , formState = FormStateInitial @@ -185,12 +194,12 @@ update flags msg model = Nothing -> ( model, Cmd.none ) - NewTask -> + NewTaskInit ct -> let ( mm, mc ) = - Comp.NotificationForm.init flags + Comp.DueItemsTaskForm.init flags ct in - ( { model | detailModel = Just mm }, Cmd.map DetailMsg mc ) + ( { model | detailModel = Just mm, channelMenuOpen = False }, Cmd.map DetailMsg mc ) SubmitResp submitType (Ok res) -> ( { model @@ -277,29 +286,32 @@ isSuccess state = False -viewForm2 : Texts -> UiSettings -> Comp.NotificationForm.Model -> List (Html Msg) +viewForm2 : Texts -> UiSettings -> Comp.DueItemsTaskForm.Model -> List (Html Msg) viewForm2 texts settings model = [ Html.map DetailMsg - (Comp.NotificationForm.view2 texts.notificationForm "flex flex-col" settings model) + (Comp.DueItemsTaskForm.view2 texts.notificationForm "flex flex-col" settings model) ] viewList2 : Texts -> Model -> List (Html Msg) viewList2 texts model = + let + menuModel = + { menuOpen = model.channelMenuOpen + , toggleMenu = ToggleChannelMenu + , menuLabel = texts.newTask + , onItem = NewTaskInit + } + in [ MB.view - { start = - [ MB.PrimaryButton - { tagger = NewTask - , label = texts.newTask - , icon = Just "fa fa-plus" - , title = texts.createNewTask - } + { start = [] + , end = + [ Comp.ChannelMenu.channelMenu texts.channelType menuModel ] - , end = [] , rootClasses = "mb-4" } , Html.map ListMsg - (Comp.NotificationList.view2 texts.notificationTable + (Comp.DueItemsTaskList.view2 texts.notificationTable model.listModel model.items ) diff --git a/modules/webapp/src/main/elm/Comp/EventSample.elm b/modules/webapp/src/main/elm/Comp/EventSample.elm new file mode 100644 index 00000000..f6a67b78 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/EventSample.elm @@ -0,0 +1,182 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.EventSample exposing (Model, Msg, init, initWith, update, viewJson, viewMessage) + +import Api +import Comp.FixedDropdown +import Data.DropdownStyle as DS +import Data.EventType exposing (EventType) +import Data.Flags exposing (Flags) +import Html exposing (..) +import Html.Attributes exposing (..) +import Http +import Json.Decode as D +import Json.Print +import Markdown +import Messages.Comp.EventSample exposing (Texts) + + +type alias Model = + { eventTypeDropdown : Comp.FixedDropdown.Model EventType + , selectedEventType : Maybe EventType + , content : String + } + + +init : Model +init = + { eventTypeDropdown = Comp.FixedDropdown.init Data.EventType.all + , selectedEventType = Nothing + , content = "" + } + + +initWith : Flags -> EventType -> ( Model, Cmd Msg ) +initWith flags evt = + ( { init | selectedEventType = Just evt } + , Api.sampleEvent flags evt SampleEvent + ) + + +type Msg + = EventTypeMsg (Comp.FixedDropdown.Msg EventType) + | SampleEvent (Result Http.Error String) + + + +--- Update + + +update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) +update flags msg model = + case msg of + EventTypeMsg lm -> + let + ( evm, evt ) = + Comp.FixedDropdown.update lm model.eventTypeDropdown + + sampleCmd = + case evt of + Just ev -> + Api.sampleEvent flags ev SampleEvent + + Nothing -> + Cmd.none + in + ( { model + | eventTypeDropdown = evm + , selectedEventType = evt + } + , sampleCmd + ) + + SampleEvent (Ok str) -> + ( { model | content = str }, Cmd.none ) + + SampleEvent (Err err) -> + ( model, Cmd.none ) + + + +--- View + + +styleBase : String +styleBase = + "bg-gray-100 dark:bg-bluegray-900 text-gray-900 dark:text-gray-100 text-sm leading-5" + + +stylePayload : String +stylePayload = + "px-2 font-mono overflow-auto max-h-96 h-full whitespace-pre" + + +styleMessage : String +styleMessage = + "-my-2 " + + +jsonPrettyCfg = + { indent = 2 + , columns = 80 + } + + +dropdownCfg texts = + { display = texts.eventType >> .name + , icon = \_ -> Nothing + , selectPlaceholder = texts.selectEvent + , style = DS.mainStyleWith "w-48" + } + + +viewJson : Texts -> Model -> Html Msg +viewJson texts model = + let + json = + Result.withDefault "" + (Json.Print.prettyString jsonPrettyCfg model.content) + in + div + [ class "flex flex-col w-full relative" + ] + [ div [ class "flex inline-flex items-center absolute top-2 right-4" ] + [ Html.map EventTypeMsg + (Comp.FixedDropdown.viewStyled2 (dropdownCfg texts) + False + model.selectedEventType + model.eventTypeDropdown + ) + ] + , div + [ class "flex pt-5" + , class styleBase + , class stylePayload + , classList [ ( "hidden", json == "" ) ] + ] + [ text json + ] + ] + + +viewMessage : Texts -> Model -> Html Msg +viewMessage texts model = + let + titleDecoder = + D.at [ "message", "title" ] D.string + + bodyDecoder = + D.at [ "message", "body" ] D.string + + title = + D.decodeString titleDecoder model.content + + body = + D.decodeString bodyDecoder model.content + in + div + [ class "flex flex-col w-full relative" + ] + [ div [ class "flex inline-flex items-center absolute top-2 right-4" ] + [ Html.map EventTypeMsg + (Comp.FixedDropdown.viewStyled2 (dropdownCfg texts) + False + model.selectedEventType + model.eventTypeDropdown + ) + ] + , div + [ class "flex flex-col py-5 px-2 markdown-preview" + , class styleBase + ] + [ Markdown.toHtml [ class styleMessage ] + (Result.withDefault "" title) + , Markdown.toHtml [ class styleMessage ] + (Result.withDefault "" body) + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm b/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm index 56d63635..2239765d 100644 --- a/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm +++ b/modules/webapp/src/main/elm/Comp/ItemDetail/SingleAttachment.elm @@ -217,6 +217,7 @@ attachHeader texts settings model _ attach = , MB.viewItem <| MB.Dropdown { linkIcon = "fa fa-bars" + , label = "" , linkClass = [ ( "ml-2", True ) , ( S.secondaryBasicButton, True ) @@ -225,21 +226,21 @@ attachHeader texts settings model _ attach = , toggleMenu = ToggleAttachmentDropdown , menuOpen = model.attachmentDropdownOpen , items = - [ { icon = "fa fa-download" + [ { icon = i [ class "fa fa-download" ] [] , label = texts.downloadFile , attrs = [ download attachName , href fileUrl ] } - , { icon = "fa fa-file" + , { icon = i [ class "fa fa-file" ] [] , label = texts.renameFile , attrs = [ href "#" , onClick (EditAttachNameStart attach.id) ] } - , { icon = "fa fa-file-archive" + , { icon = i [ class "fa fa-file-archive" ] [] , label = texts.downloadOriginalArchiveFile , attrs = [ href (fileUrl ++ "/archive") @@ -247,7 +248,7 @@ attachHeader texts settings model _ attach = , classList [ ( "hidden", not hasArchive ) ] ] } - , { icon = "fa fa-external-link-alt" + , { icon = i [ class "fa fa-external-link-alt" ] [] , label = texts.originalFile , attrs = [ href (fileUrl ++ "/original") @@ -257,31 +258,31 @@ attachHeader texts settings model _ attach = } , { icon = if isAttachMetaOpen model attach.id then - "fa fa-toggle-on" + i [ class "fa fa-toggle-on" ] [] else - "fa fa-toggle-off" + i [ class "fa fa-toggle-off" ] [] , label = texts.viewExtractedData , attrs = [ onClick (AttachMetaClick attach.id) , href "#" ] } - , { icon = "fa fa-redo-alt" + , { icon = i [ class "fa fa-redo-alt" ] [] , label = texts.reprocessFile , attrs = [ onClick (RequestReprocessFile attach.id) , href "#" ] } - , { icon = Icons.showQr + , { icon = i [ class Icons.showQr ] [] , label = texts.showQrCode , attrs = [ onClick (ToggleShowQrAttach attach.id) , href "#" ] } - , { icon = "fa fa-trash" + , { icon = i [ class "fa fa-trash" ] [] , label = texts.deleteThisFile , attrs = [ onClick (RequestDeleteAttachment attach.id) diff --git a/modules/webapp/src/main/elm/Comp/MenuBar.elm b/modules/webapp/src/main/elm/Comp/MenuBar.elm index e43e6ffe..b29918bb 100644 --- a/modules/webapp/src/main/elm/Comp/MenuBar.elm +++ b/modules/webapp/src/main/elm/Comp/MenuBar.elm @@ -8,6 +8,7 @@ module Comp.MenuBar exposing ( ButtonData , CheckboxData + , DropdownMenu , Item(..) , MenuBar , TextInputData @@ -85,6 +86,7 @@ type alias LabelData = type alias DropdownData msg = { linkIcon : String , linkClass : List ( String, Bool ) + , label : String , toggleMenu : msg , menuOpen : Bool , items : List (DropdownMenu msg) @@ -92,7 +94,7 @@ type alias DropdownData msg = type alias DropdownMenu msg = - { icon : String + { icon : Html msg , label : String , attrs : List (Attribute msg) } @@ -175,11 +177,7 @@ makeDropdown model = menuItem m = a (class itemStyle :: m.attrs) - [ i - [ class m.icon - , classList [ ( "hidden", m.icon == "" ) ] - ] - [] + [ m.icon , span [ class "ml-2" , classList [ ( "hidden", m.label == "" ) ] @@ -196,6 +194,13 @@ makeDropdown model = , onClick model.toggleMenu ] [ i [ class model.linkIcon ] [] + , if model.label == "" then + span [ class "hidden" ] [] + + else + span [ class "ml-2" ] + [ text model.label + ] ] , div [ class menuStyle diff --git a/modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm b/modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm new file mode 100644 index 00000000..ffcf9d73 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm @@ -0,0 +1,117 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationGotifyForm exposing (Model, Msg, init, initWith, update, view) + +import Api.Model.NotificationGotify exposing (NotificationGotify) +import Comp.Basic as B +import Data.NotificationChannel +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput) +import Messages.Comp.NotificationGotifyForm exposing (Texts) +import Styles as S + + +type alias Model = + { hook : NotificationGotify + } + + +init : Model +init = + { hook = Data.NotificationChannel.setTypeGotify Api.Model.NotificationGotify.empty + } + + +initWith : NotificationGotify -> Model +initWith hook = + { hook = Data.NotificationChannel.setTypeGotify hook + } + + +type Msg + = SetUrl String + | SetAppKey String + + + +--- Update + + +update : Msg -> Model -> ( Model, Maybe NotificationGotify ) +update msg model = + let + newHook = + updateHook msg model.hook + in + ( { model | hook = newHook }, check newHook ) + + +check : NotificationGotify -> Maybe NotificationGotify +check hook = + Just hook + + +updateHook : Msg -> NotificationGotify -> NotificationGotify +updateHook msg hook = + case msg of + SetUrl s -> + { hook | url = s } + + SetAppKey s -> + { hook | appKey = s } + + + +--- View + + +view : Texts -> Model -> Html Msg +view texts model = + div [] + [ div + [ class "mb-2" + ] + [ label + [ for "gotifyurl" + , class S.inputLabel + ] + [ text texts.gotifyUrl + , B.inputRequired + ] + , input + [ type_ "text" + , onInput SetUrl + , placeholder texts.gotifyUrl + , value model.hook.url + , name "gotifyurl" + , class S.textInput + ] + [] + ] + , div + [ class "mb-2" + ] + [ label + [ for "appkey" + , class S.inputLabel + ] + [ text texts.appKey + , B.inputRequired + ] + , input + [ type_ "text" + , onInput SetAppKey + , placeholder texts.appKey + , value model.hook.appKey + , name "appkey" + , class S.textInput + ] + [] + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationHookForm.elm b/modules/webapp/src/main/elm/Comp/NotificationHookForm.elm new file mode 100644 index 00000000..f1067a25 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationHookForm.elm @@ -0,0 +1,317 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationHookForm exposing + ( Model + , Msg(..) + , channelType + , getHook + , init + , initWith + , update + , view + ) + +import Comp.Basic as B +import Comp.ChannelForm +import Comp.Dropdown +import Comp.EventSample +import Comp.MenuBar as MB +import Comp.NotificationTest +import Data.ChannelType exposing (ChannelType) +import Data.DropdownStyle as DS +import Data.EventType exposing (EventType) +import Data.Flags exposing (Flags) +import Data.NotificationHook exposing (NotificationHook) +import Data.UiSettings exposing (UiSettings) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput) +import Messages.Comp.NotificationHookForm exposing (Texts) +import Styles as S +import Util.Maybe + + +type alias Model = + { hook : NotificationHook + , enabled : Bool + , channelModel : Comp.ChannelForm.Model + , eventsDropdown : Comp.Dropdown.Model EventType + , eventSampleModel : Comp.EventSample.Model + , testDeliveryModel : Comp.NotificationTest.Model + , allEvents : Bool + , eventFilter : Maybe String + } + + +init : Flags -> ChannelType -> ( Model, Cmd Msg ) +init flags ct = + let + ( cm, cc ) = + Comp.ChannelForm.init flags ct + + ( esm, esc ) = + Comp.EventSample.initWith flags Data.EventType.TagsChanged + in + ( { hook = Data.NotificationHook.empty ct + , enabled = True + , channelModel = cm + , eventsDropdown = + Comp.Dropdown.makeMultipleList + { options = Data.EventType.all + , selected = [] + } + , eventSampleModel = esm + , testDeliveryModel = Comp.NotificationTest.init + , allEvents = False + , eventFilter = Nothing + } + , Cmd.batch + [ Cmd.map ChannelFormMsg cc + , Cmd.map EventSampleMsg esc + ] + ) + + +initWith : Flags -> NotificationHook -> ( Model, Cmd Msg ) +initWith flags h = + let + ( cm, cc ) = + Comp.ChannelForm.initWith flags h.channel + + ( esm, esc ) = + Comp.EventSample.initWith flags Data.EventType.TagsChanged + in + ( { hook = h + , enabled = h.enabled + , channelModel = cm + , eventsDropdown = + Comp.Dropdown.makeMultipleList + { options = Data.EventType.all + , selected = h.events + } + , eventSampleModel = esm + , testDeliveryModel = Comp.NotificationTest.init + , allEvents = h.allEvents + , eventFilter = h.eventFilter + } + , Cmd.batch + [ Cmd.map ChannelFormMsg cc + , Cmd.map EventSampleMsg esc + ] + ) + + +channelType : Model -> ChannelType +channelType model = + Comp.ChannelForm.channelType model.channelModel + + +getHook : Model -> Maybe NotificationHook +getHook model = + let + events = + let + ev = + Comp.Dropdown.getSelected model.eventsDropdown + in + if List.isEmpty ev && not model.allEvents then + Nothing + + else + Just ev + + channel = + Comp.ChannelForm.getChannel model.channelModel + + mkHook ev ch = + NotificationHook model.hook.id model.enabled ch model.allEvents model.eventFilter ev + in + Maybe.map2 mkHook events channel + + +type Msg + = ToggleEnabled + | ChannelFormMsg Comp.ChannelForm.Msg + | EventMsg (Comp.Dropdown.Msg EventType) + | EventSampleMsg Comp.EventSample.Msg + | DeliveryTestMsg Comp.NotificationTest.Msg + | ToggleAllEvents + | SetEventFilter String + + +update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) +update flags msg model = + case msg of + SetEventFilter str -> + ( { model | eventFilter = Util.Maybe.fromString str }, Cmd.none ) + + ToggleAllEvents -> + ( { model | allEvents = not model.allEvents } + , Cmd.none + ) + + ToggleEnabled -> + ( { model | enabled = not model.enabled } + , Cmd.none + ) + + ChannelFormMsg lm -> + let + ( cm, cc ) = + Comp.ChannelForm.update flags lm model.channelModel + in + ( { model | channelModel = cm }, Cmd.map ChannelFormMsg cc ) + + EventMsg lm -> + if model.allEvents then + ( model, Cmd.none ) + + else + let + ( em, ec ) = + Comp.Dropdown.update lm model.eventsDropdown + in + ( { model | eventsDropdown = em }, Cmd.map EventMsg ec ) + + EventSampleMsg lm -> + let + ( esm, esc ) = + Comp.EventSample.update flags lm model.eventSampleModel + in + ( { model | eventSampleModel = esm }, Cmd.map EventSampleMsg esc ) + + DeliveryTestMsg lm -> + case getHook model of + Just hook -> + let + ( ntm, ntc ) = + Comp.NotificationTest.update flags hook lm model.testDeliveryModel + in + ( { model | testDeliveryModel = ntm }, Cmd.map DeliveryTestMsg ntc ) + + Nothing -> + ( model, Cmd.none ) + + + +--- View + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + let + connectionCfg = + { makeOption = \a -> { text = (texts.eventType a).name, additional = (texts.eventType a).info } + , placeholder = texts.selectEvents + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + + formHeader txt = + h2 [ class S.formHeader, class "mt-2" ] + [ text txt + ] + in + div + [ class "flex flex-col" ] + [ div [ class "mb-4" ] + [ MB.viewItem <| + MB.Checkbox + { tagger = \_ -> ToggleEnabled + , label = texts.enableDisable + , value = model.enabled + , id = "notify-enabled" + } + ] + , div [ class "mb-4" ] + [ formHeader (texts.channelHeader (Comp.ChannelForm.channelType model.channelModel)) + , Html.map ChannelFormMsg + (Comp.ChannelForm.view texts.channelForm settings model.channelModel) + ] + , div [ class "mb-4" ] + [ formHeader texts.events + , MB.viewItem <| + MB.Checkbox + { tagger = \_ -> ToggleAllEvents + , label = texts.toggleAllEvents + , value = model.allEvents + , id = "notify-on-all-events" + } + ] + , div + [ class "mb-4" + , classList [ ( "disabled", model.allEvents ) ] + ] + [ label [ class S.inputLabel ] + [ text texts.events + , B.inputRequired + ] + , Html.map EventMsg + (Comp.Dropdown.view2 + connectionCfg + settings + model.eventsDropdown + ) + , span [ class "opacity-50 text-sm" ] + [ text texts.eventsInfo + ] + ] + , div [ class "mb-4" ] + [ label [ class S.inputLabel ] + [ text texts.eventFilter + , a + [ class "float-right" + , class S.link + , href "https://docspell.org/docs/jsonminiquery/" + , target "_blank" + ] + [ i [ class "fa fa-question" ] [] + , span [ class "pl-2" ] + [ text texts.eventFilterClickForHelp + ] + ] + ] + , input + [ type_ "text" + , onInput SetEventFilter + , class S.textInput + , Maybe.withDefault "" model.eventFilter + |> value + ] + [] + , span [ class "opacity-50 text-sm" ] + [ text texts.eventFilterInfo + ] + ] + , div + [ class "mt-4" + , classList [ ( "hidden", channelType model /= Data.ChannelType.Http ) ] + ] + [ h3 [ class S.header3 ] + [ text texts.samplePayload + ] + , Html.map EventSampleMsg + (Comp.EventSample.viewJson texts.eventSample model.eventSampleModel) + ] + , div + [ class "mt-4" + , classList [ ( "hidden", channelType model == Data.ChannelType.Http ) ] + ] + [ formHeader texts.samplePayload + , Html.map EventSampleMsg + (Comp.EventSample.viewMessage texts.eventSample model.eventSampleModel) + ] + , div [ class "mt-4" ] + [ formHeader "Test Delviery" + , Html.map DeliveryTestMsg + (Comp.NotificationTest.view + { runDisabled = getHook model == Nothing } + model.testDeliveryModel + ) + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationHookManage.elm b/modules/webapp/src/main/elm/Comp/NotificationHookManage.elm new file mode 100644 index 00000000..0d175640 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationHookManage.elm @@ -0,0 +1,475 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationHookManage exposing + ( Model + , Msg + , init + , update + , view + ) + +import Api +import Api.Model.BasicResult exposing (BasicResult) +import Comp.Basic as B +import Comp.ChannelMenu +import Comp.MenuBar as MB +import Comp.NotificationHookForm +import Comp.NotificationHookTable +import Data.ChannelType exposing (ChannelType) +import Data.Flags exposing (Flags) +import Data.NotificationHook exposing (NotificationHook) +import Data.UiSettings exposing (UiSettings) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick) +import Http +import Messages.Comp.NotificationHookManage exposing (Texts) +import Styles as S + + +type alias Model = + { listModel : Comp.NotificationHookTable.Model + , detailModel : Maybe Comp.NotificationHookForm.Model + , items : List NotificationHook + , deleteConfirm : DeleteConfirm + , loading : Bool + , formState : FormState + , newHookMenuOpen : Bool + , jsonFilterError : Maybe String + } + + +type DeleteConfirm + = DeleteConfirmOff + | DeleteConfirmOn + + +type SubmitType + = SubmitDelete + | SubmitUpdate + | SubmitCreate + + +type FormState + = FormStateInitial + | FormErrorHttp Http.Error + | FormSubmitSuccessful SubmitType + | FormErrorSubmit String + | FormErrorInvalid + + +type Msg + = TableMsg Comp.NotificationHookTable.Msg + | DetailMsg Comp.NotificationHookForm.Msg + | GetDataResp (Result Http.Error (List NotificationHook)) + | ToggleNewHookMenu + | SubmitResp SubmitType (Result Http.Error BasicResult) + | NewHookInit ChannelType + | BackToTable + | Submit + | RequestDelete + | CancelDelete + | DeleteHookNow String + | VerifyFilterResp NotificationHook (Result Http.Error BasicResult) + + +initModel : Model +initModel = + { listModel = Comp.NotificationHookTable.init + , detailModel = Nothing + , items = [] + , loading = False + , formState = FormStateInitial + , newHookMenuOpen = False + , deleteConfirm = DeleteConfirmOff + , jsonFilterError = Nothing + } + + +initCmd : Flags -> Cmd Msg +initCmd flags = + Api.getHooks flags GetDataResp + + +init : Flags -> ( Model, Cmd Msg ) +init flags = + ( initModel, initCmd flags ) + + + +--- Update + + +update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) +update flags msg model = + case msg of + VerifyFilterResp hook (Ok res) -> + if res.success then + postHook flags hook model + + else + ( { model + | loading = False + , formState = FormErrorInvalid + , jsonFilterError = Just res.message + } + , Cmd.none + ) + + VerifyFilterResp _ (Err err) -> + ( { model | formState = FormErrorHttp err } + , Cmd.none + ) + + GetDataResp (Ok res) -> + ( { model + | items = res + , formState = FormStateInitial + } + , Cmd.none + ) + + GetDataResp (Err err) -> + ( { model | formState = FormErrorHttp err } + , Cmd.none + ) + + TableMsg lm -> + let + ( mm, action ) = + Comp.NotificationHookTable.update flags lm model.listModel + + ( detail, cmd ) = + case action of + Comp.NotificationHookTable.NoAction -> + ( Nothing, Cmd.none ) + + Comp.NotificationHookTable.EditAction hook -> + let + ( dm, dc ) = + Comp.NotificationHookForm.initWith flags hook + in + ( Just dm, Cmd.map DetailMsg dc ) + in + ( { model + | listModel = mm + , detailModel = detail + } + , cmd + ) + + DetailMsg lm -> + case model.detailModel of + Just dm -> + let + ( mm, mc ) = + Comp.NotificationHookForm.update flags lm dm + in + ( { model | detailModel = Just mm } + , Cmd.map DetailMsg mc + ) + + Nothing -> + ( model, Cmd.none ) + + ToggleNewHookMenu -> + ( { model | newHookMenuOpen = not model.newHookMenuOpen }, Cmd.none ) + + SubmitResp submitType (Ok res) -> + ( { model + | formState = + if res.success then + FormSubmitSuccessful submitType + + else + FormErrorSubmit res.message + , detailModel = + if submitType == SubmitDelete then + Nothing + + else + model.detailModel + , loading = False + } + , if submitType == SubmitDelete then + initCmd flags + + else + Cmd.none + ) + + SubmitResp _ (Err err) -> + ( { model | formState = FormErrorHttp err, loading = False } + , Cmd.none + ) + + NewHookInit ct -> + let + ( mm, mc ) = + Comp.NotificationHookForm.init flags ct + in + ( { model | detailModel = Just mm, newHookMenuOpen = False }, Cmd.map DetailMsg mc ) + + BackToTable -> + ( { model | detailModel = Nothing }, initCmd flags ) + + Submit -> + case model.detailModel of + Just dm -> + case Comp.NotificationHookForm.getHook dm of + Just data -> + case data.eventFilter of + Nothing -> + postHook flags data model + + Just jf -> + ( { model | loading = True }, Api.verifyJsonFilter flags jf (VerifyFilterResp data) ) + + Nothing -> + ( { model | formState = FormErrorInvalid }, Cmd.none ) + + Nothing -> + ( model, Cmd.none ) + + RequestDelete -> + ( { model | deleteConfirm = DeleteConfirmOn }, Cmd.none ) + + CancelDelete -> + ( { model | deleteConfirm = DeleteConfirmOff }, Cmd.none ) + + DeleteHookNow id -> + ( { model | deleteConfirm = DeleteConfirmOff, loading = True } + , Api.deleteHook flags id (SubmitResp SubmitDelete) + ) + + +postHook : Flags -> NotificationHook -> Model -> ( Model, Cmd Msg ) +postHook flags hook model = + if hook.id == "" then + ( { model | loading = True }, Api.createHook flags hook (SubmitResp SubmitCreate) ) + + else + ( { model | loading = True }, Api.updateHook flags hook (SubmitResp SubmitUpdate) ) + + + +--- View2 + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + div [ class "flex flex-col" ] + (case model.detailModel of + Just msett -> + viewForm texts settings model msett + + Nothing -> + viewList texts model + ) + + +viewState : Texts -> Model -> Html Msg +viewState texts model = + div + [ classList + [ ( S.errorMessage, model.formState /= FormStateInitial ) + , ( S.successMessage, isSuccess model.formState ) + , ( "hidden", model.formState == FormStateInitial ) + ] + , class "mb-2" + ] + [ case model.formState of + FormStateInitial -> + text "" + + FormSubmitSuccessful SubmitCreate -> + text texts.hookCreated + + FormSubmitSuccessful SubmitUpdate -> + text texts.hookUpdated + + FormSubmitSuccessful SubmitDelete -> + text texts.hookDeleted + + FormErrorSubmit m -> + text m + + FormErrorHttp err -> + text (texts.httpError err) + + FormErrorInvalid -> + case model.jsonFilterError of + Just m -> + text (texts.invalidJsonFilter m) + + Nothing -> + text texts.formInvalid + ] + + +isSuccess : FormState -> Bool +isSuccess state = + case state of + FormSubmitSuccessful _ -> + True + + _ -> + False + + +viewForm : Texts -> UiSettings -> Model -> Comp.NotificationHookForm.Model -> List (Html Msg) +viewForm texts settings outerModel model = + let + newHook = + model.hook.id == "" + + headline = + case Comp.NotificationHookForm.channelType model of + Data.ChannelType.Matrix -> + span [] + [ text texts.integrate + , a + [ href "https://matrix.org" + , target "_blank" + , class S.link + , class "mx-3" + ] + [ i [ class "fa fa-external-link-alt mr-1" ] [] + , text "Matrix" + ] + , text texts.intoDocspell + ] + + Data.ChannelType.Mail -> + span [] + [ text texts.notifyEmailInfo + ] + + Data.ChannelType.Gotify -> + span [] + [ text texts.integrate + , a + [ href "https://gotify.net" + , target "_blank" + , class S.link + , class "mx-3" + ] + [ i [ class "fa fa-external-link-alt mr-1" ] [] + , text "Gotify" + ] + , text texts.intoDocspell + ] + + Data.ChannelType.Http -> + span [] + [ text texts.postRequestInfo + ] + in + [ h1 [ class S.header2 ] + [ Data.ChannelType.icon (Comp.NotificationHookForm.channelType model) "w-8 h-8 inline-block mr-4" + , if newHook then + text texts.addWebhook + + else + text texts.updateWebhook + ] + , div [ class "pt-2 pb-4 font-medium" ] + [ headline + ] + , MB.view + { start = + [ MB.CustomElement <| + B.primaryButton + { handler = onClick Submit + , title = texts.basics.submitThisForm + , icon = "fa fa-save" + , label = texts.basics.submit + , disabled = False + , attrs = [ href "#" ] + } + , MB.SecondaryButton + { tagger = BackToTable + , title = texts.basics.backToList + , icon = Just "fa fa-arrow-left" + , label = texts.basics.backToList + } + ] + , end = + if not newHook then + [ MB.DeleteButton + { tagger = RequestDelete + , title = texts.deleteThisHook + , icon = Just "fa fa-trash" + , label = texts.basics.delete + } + ] + + else + [] + , rootClasses = "mb-4" + } + , div [ class "mt-2" ] + [ viewState texts outerModel + ] + , Html.map DetailMsg + (Comp.NotificationHookForm.view texts.notificationForm settings model) + , B.loadingDimmer + { active = outerModel.loading + , label = texts.basics.loading + } + , B.contentDimmer + (outerModel.deleteConfirm == DeleteConfirmOn) + (div [ class "flex flex-col" ] + [ div [ class "text-lg" ] + [ i [ class "fa fa-info-circle mr-2" ] [] + , text texts.reallyDeleteHook + ] + , div [ class "mt-4 flex flex-row items-center" ] + [ B.deleteButton + { label = texts.basics.yes + , icon = "fa fa-check" + , disabled = False + , handler = onClick (DeleteHookNow model.hook.id) + , attrs = [ href "#" ] + } + , B.secondaryButton + { label = texts.basics.no + , icon = "fa fa-times" + , disabled = False + , handler = onClick CancelDelete + , attrs = [ href "#", class "ml-2" ] + } + ] + ] + ) + ] + + +viewList : Texts -> Model -> List (Html Msg) +viewList texts model = + let + menuModel = + { menuOpen = model.newHookMenuOpen + , toggleMenu = ToggleNewHookMenu + , menuLabel = texts.newHook + , onItem = NewHookInit + } + in + [ MB.view + { start = [] + , end = + [ Comp.ChannelMenu.channelMenu texts.channelType menuModel + ] + , rootClasses = "mb-4" + } + , Html.map TableMsg + (Comp.NotificationHookTable.view texts.notificationTable + model.listModel + model.items + ) + ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationHookTable.elm b/modules/webapp/src/main/elm/Comp/NotificationHookTable.elm new file mode 100644 index 00000000..8188a1df --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationHookTable.elm @@ -0,0 +1,106 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationHookTable exposing + ( Action(..) + , Model + , Msg(..) + , init + , update + , view + ) + +import Comp.Basic as B +import Data.ChannelType +import Data.EventType +import Data.Flags exposing (Flags) +import Data.NotificationChannel +import Data.NotificationHook exposing (NotificationHook) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick) +import Messages.Comp.NotificationHookTable exposing (Texts) +import Styles as S +import Util.Html + + +type alias Model = + {} + + +type Action + = NoAction + | EditAction NotificationHook + + +init : Model +init = + {} + + +type Msg + = Select NotificationHook + + +update : Flags -> Msg -> Model -> ( Model, Action ) +update _ msg model = + case msg of + Select hook -> + ( model, EditAction hook ) + + + +--- View + + +view : Texts -> Model -> List NotificationHook -> Html Msg +view texts model hooks = + table [ class S.tableMain ] + [ thead [] + [ tr [] + [ th [ class "" ] [] + , th [ class "text-center mr-2" ] + [ i [ class "fa fa-check" ] [] + ] + , th [ class "text-left" ] + [ text texts.channel + ] + , th [ class "text-left hidden sm:table-cell" ] + [ text texts.events + ] + ] + ] + , tbody [] + (List.map (renderNotificationHookLine texts model) hooks) + ] + + +renderNotificationHookLine : Texts -> Model -> NotificationHook -> Html Msg +renderNotificationHookLine texts model hook = + let + eventName = + texts.eventType >> .name + in + tr + [ class S.tableRow + ] + [ B.editLinkTableCell texts.basics.edit (Select hook) + , td [ class "w-px whitespace-nowrap px-2 text-center" ] + [ Util.Html.checkbox2 hook.enabled + ] + , td [ class "text-left py-4 md:py-2" ] + [ Data.NotificationChannel.channelType hook.channel + |> Maybe.map Data.ChannelType.asString + |> Maybe.withDefault "-" + |> text + ] + , td [ class "text-left hidden sm:table-cell" ] + [ List.map eventName hook.events + |> String.join ", " + |> text + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationHttpForm.elm b/modules/webapp/src/main/elm/Comp/NotificationHttpForm.elm new file mode 100644 index 00000000..1e637796 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationHttpForm.elm @@ -0,0 +1,99 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationHttpForm exposing (Model, Msg, init, initWith, update, view) + +import Api.Model.NotificationHttp exposing (NotificationHttp) +import Comp.Basic as B +import Data.NotificationChannel +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput) +import Messages.Comp.NotificationHttpForm exposing (Texts) +import Styles as S + + +type alias Model = + { hook : NotificationHttp + } + + +init : Model +init = + { hook = + Data.NotificationChannel.setTypeHttp + Api.Model.NotificationHttp.empty + } + + +initWith : NotificationHttp -> Model +initWith hook = + { hook = Data.NotificationChannel.setTypeHttp hook + } + + +type Msg + = SetUrl String + + + +--- Update + + +update : Msg -> Model -> ( Model, Maybe NotificationHttp ) +update msg model = + let + newHook = + updateHook msg model.hook + in + ( { model | hook = newHook }, check newHook ) + + +check : NotificationHttp -> Maybe NotificationHttp +check hook = + if hook.url == "" then + Nothing + + else + Just hook + + +updateHook : Msg -> NotificationHttp -> NotificationHttp +updateHook msg hook = + case msg of + SetUrl s -> + { hook | url = s } + + + +--- View + + +view : Texts -> Model -> Html Msg +view texts model = + div [] + [ div + [ class "mb-2" + ] + [ label + [ for "httpurl" + , class S.inputLabel + ] + [ text texts.httpUrl + , B.inputRequired + ] + , input + [ type_ "text" + , onInput SetUrl + , placeholder texts.httpUrl + , value model.hook.url + , name "httpurl" + , class S.textInput + ] + [] + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationMailForm.elm b/modules/webapp/src/main/elm/Comp/NotificationMailForm.elm new file mode 100644 index 00000000..ce756826 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationMailForm.elm @@ -0,0 +1,236 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationMailForm exposing (Model, Msg, init, initWith, update, view) + +import Api +import Api.Model.EmailSettingsList exposing (EmailSettingsList) +import Api.Model.NotificationMail exposing (NotificationMail) +import Comp.Basic as B +import Comp.Dropdown +import Comp.EmailInput +import Data.DropdownStyle as DS +import Data.Flags exposing (Flags) +import Data.NotificationChannel +import Data.UiSettings exposing (UiSettings) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput) +import Http +import Messages.Comp.NotificationMailForm exposing (Texts) +import Styles as S + + +type alias Model = + { hook : NotificationMail + , connectionModel : Comp.Dropdown.Model String + , recipients : List String + , recipientsModel : Comp.EmailInput.Model + , formState : FormState + } + + +type FormState + = FormStateInitial + | FormStateHttpError Http.Error + | FormStateInvalid ValidateError + + +type ValidateError + = ValidateConnectionMissing + + +init : Flags -> ( Model, Cmd Msg ) +init flags = + ( { hook = Data.NotificationChannel.setTypeMail Api.Model.NotificationMail.empty + , connectionModel = Comp.Dropdown.makeSingle + , recipients = [] + , recipientsModel = Comp.EmailInput.init + , formState = FormStateInitial + } + , Cmd.batch + [ Api.getMailSettings flags "" ConnResp + ] + ) + + +initWith : Flags -> NotificationMail -> ( Model, Cmd Msg ) +initWith flags hook = + let + ( mm, mc ) = + init flags + + ( cm, _ ) = + Comp.Dropdown.update (Comp.Dropdown.SetSelection [ hook.connection ]) mm.connectionModel + in + ( { mm + | hook = Data.NotificationChannel.setTypeMail hook + , recipients = hook.recipients + , connectionModel = cm + } + , mc + ) + + +type Msg + = ConnResp (Result Http.Error EmailSettingsList) + | ConnMsg (Comp.Dropdown.Msg String) + | RecipientMsg Comp.EmailInput.Msg + + + +--- Update + + +check : Model -> Maybe NotificationMail +check model = + let + formState = + if model.formState == FormStateInitial then + Just () + + else + Nothing + + recipients = + if List.isEmpty model.recipients then + Nothing + + else + Just model.recipients + + connection = + Comp.Dropdown.getSelected model.connectionModel + |> List.head + + h = + model.hook + + makeHook _ rec conn = + { h | connection = conn, recipients = rec } + in + Maybe.map3 makeHook formState recipients connection + + +update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Maybe NotificationMail ) +update flags msg model = + case msg of + ConnResp (Ok list) -> + let + names = + List.map .name list.items + + cm = + Comp.Dropdown.makeSingleList + { options = names + , selected = List.head names + } + + model_ = + { model + | connectionModel = cm + , formState = + if names == [] then + FormStateInvalid ValidateConnectionMissing + + else + FormStateInitial + } + in + ( model_ + , Cmd.none + , check model_ + ) + + ConnResp (Err err) -> + ( { model | formState = FormStateHttpError err } + , Cmd.none + , Nothing + ) + + ConnMsg lm -> + let + ( cm, cc ) = + Comp.Dropdown.update lm model.connectionModel + + model_ = + { model + | connectionModel = cm + , formState = FormStateInitial + } + in + ( model_ + , Cmd.map ConnMsg cc + , check model_ + ) + + RecipientMsg lm -> + let + ( em, ec, rec ) = + Comp.EmailInput.update flags model.recipients lm model.recipientsModel + + model_ = + { model + | recipients = rec + , recipientsModel = em + , formState = FormStateInitial + } + in + ( model_ + , Cmd.map RecipientMsg ec + , check model_ + ) + + + +--- View + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + let + connectionCfg = + { makeOption = \a -> { text = a, additional = "" } + , placeholder = texts.selectConnection + , labelColor = \_ -> \_ -> "" + , style = DS.mainStyle + } + in + div [] + [ div [ class "mb-4" ] + [ label [ class S.inputLabel ] + [ text texts.sendVia + , B.inputRequired + ] + , Html.map ConnMsg + (Comp.Dropdown.view2 + connectionCfg + settings + model.connectionModel + ) + , span [ class "opacity-50 text-sm" ] + [ text texts.sendViaInfo + ] + ] + , div [ class "" ] + [ label + [ class S.inputLabel + ] + [ text texts.recipients + , B.inputRequired + ] + , Html.map RecipientMsg + (Comp.EmailInput.view2 + { style = DS.mainStyle, placeholder = texts.recipients } + model.recipients + model.recipientsModel + ) + , span [ class "opacity-50 text-sm" ] + [ text texts.recipientsInfo + ] + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationMatrixForm.elm b/modules/webapp/src/main/elm/Comp/NotificationMatrixForm.elm new file mode 100644 index 00000000..8f4104b0 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationMatrixForm.elm @@ -0,0 +1,140 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationMatrixForm exposing (Model, Msg, init, initWith, update, view) + +import Api.Model.NotificationMatrix exposing (NotificationMatrix) +import Comp.Basic as B +import Data.NotificationChannel +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput) +import Messages.Comp.NotificationMatrixForm exposing (Texts) +import Styles as S + + +type alias Model = + { hook : NotificationMatrix + } + + +init : Model +init = + { hook = Data.NotificationChannel.setTypeMatrix Api.Model.NotificationMatrix.empty + } + + +initWith : NotificationMatrix -> Model +initWith hook = + { hook = Data.NotificationChannel.setTypeMatrix hook + } + + +type Msg + = SetHomeServer String + | SetRoomId String + | SetAccessKey String + + + +--- Update + + +update : Msg -> Model -> ( Model, Maybe NotificationMatrix ) +update msg model = + let + newHook = + updateHook msg model.hook + in + ( { model | hook = newHook }, check newHook ) + + +check : NotificationMatrix -> Maybe NotificationMatrix +check hook = + Just hook + + +updateHook : Msg -> NotificationMatrix -> NotificationMatrix +updateHook msg hook = + case msg of + SetHomeServer s -> + { hook | homeServer = s } + + SetRoomId s -> + { hook | roomId = s } + + SetAccessKey s -> + { hook | accessToken = s } + + + +--- View + + +view : Texts -> Model -> Html Msg +view texts model = + div [] + [ div + [ class "mb-2" + ] + [ label + [ for "homeserver" + , class S.inputLabel + ] + [ text texts.homeServer + , B.inputRequired + ] + , input + [ type_ "text" + , onInput SetHomeServer + , placeholder texts.homeServer + , value model.hook.homeServer + , name "homeserver" + , class S.textInput + ] + [] + ] + , div + [ class "mb-2" + ] + [ label + [ for "roomid" + , class S.inputLabel + ] + [ text texts.roomId + , B.inputRequired + ] + , input + [ type_ "text" + , onInput SetRoomId + , placeholder texts.roomId + , value model.hook.roomId + , name "roomid" + , class S.textInput + ] + [] + ] + , div + [ class "mb-2" + ] + [ label + [ for "accesskey" + , class S.inputLabel + ] + [ text texts.accessKey + , B.inputRequired + ] + , textarea + [ onInput SetAccessKey + , placeholder texts.accessKey + , value model.hook.accessToken + , name "accesskey" + , class S.textAreaInput + ] + [] + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/NotificationTest.elm b/modules/webapp/src/main/elm/Comp/NotificationTest.elm new file mode 100644 index 00000000..f7aaab4d --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/NotificationTest.elm @@ -0,0 +1,146 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.NotificationTest exposing (Model, Msg, ViewConfig, init, update, view) + +import Api +import Api.Model.NotificationChannelTestResult exposing (NotificationChannelTestResult) +import Comp.Basic as B +import Comp.MenuBar as MB +import Data.Flags exposing (Flags) +import Data.NotificationHook exposing (NotificationHook) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick) +import Http + + +type Model + = ModelInit + | ModelResp NotificationChannelTestResult + | ModelHttpError Http.Error + | ModelLoading + + +init : Model +init = + ModelInit + + +type Msg + = RunTest + | TestResp (Result Http.Error NotificationChannelTestResult) + + +hasResponse : Model -> Bool +hasResponse model = + case model of + ModelResp _ -> + True + + _ -> + False + + + +--- Update + + +update : Flags -> NotificationHook -> Msg -> Model -> ( Model, Cmd Msg ) +update flags hook msg model = + case msg of + RunTest -> + case model of + ModelLoading -> + ( model, Cmd.none ) + + _ -> + ( ModelLoading, Api.testHook flags hook TestResp ) + + TestResp (Ok res) -> + ( ModelResp res, Cmd.none ) + + TestResp (Err err) -> + ( ModelHttpError err, Cmd.none ) + + + +--- View + + +type alias ViewConfig = + { runDisabled : Bool + } + + +styleBase : String +styleBase = + "bg-gray-100 dark:bg-bluegray-900 text-gray-900 dark:text-gray-100 text-sm leading-5" + + +stylePayload : String +stylePayload = + "px-2 font-mono overflow-auto h-full whitespace-pre " + + +view : ViewConfig -> Model -> Html Msg +view cfg model = + div + [ class "flex flex-col w-full" + ] + [ MB.view + { start = + case model of + ModelResp res -> + [ MB.CustomElement <| + if res.success then + div [ class "text-3xl text-green-500" ] + [ i [ class "fa fa-check" ] [] + ] + + else + div [ class "text-3xl text-red-500" ] + [ i [ class "fa fa-times" ] [] + ] + ] + + _ -> + [] + , end = + [ MB.CustomElement <| + B.primaryButton + { label = "Test Delivery" + , disabled = cfg.runDisabled || model == ModelLoading + , icon = + if model == ModelLoading then + "fa fa-cog animate-spin" + + else + "fa fa-cog" + , handler = onClick RunTest + , attrs = [ href "#" ] + } + ] + , rootClasses = "mb-1" + } + , case model of + ModelResp res -> + div + [ class "flex flex-col py-5 px-2" + , class styleBase + , class stylePayload + ] + [ text (String.join "\n" res.messages) + ] + + ModelHttpError err -> + div [ class "" ] + [] + + _ -> + span [ class "hidden" ] [] + ] diff --git a/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskForm.elm b/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskForm.elm new file mode 100644 index 00000000..098a61aa --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskForm.elm @@ -0,0 +1,484 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.PeriodicQueryTaskForm exposing + ( Action(..) + , Model + , Msg + , UpdateResult + , init + , initWith + , update + , view + ) + +import Comp.Basic as B +import Comp.CalEventInput +import Comp.ChannelForm +import Comp.MenuBar as MB +import Comp.PowerSearchInput +import Data.CalEvent exposing (CalEvent) +import Data.ChannelType exposing (ChannelType) +import Data.Flags exposing (Flags) +import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings) +import Data.UiSettings exposing (UiSettings) +import Data.Validated exposing (Validated(..)) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onInput) +import Http +import Messages.Comp.PeriodicQueryTaskForm exposing (Texts) +import Styles as S +import Util.Maybe + + +type alias Model = + { settings : PeriodicQuerySettings + , enabled : Bool + , summary : Maybe String + , schedule : Maybe CalEvent + , scheduleModel : Comp.CalEventInput.Model + , queryModel : Comp.PowerSearchInput.Model + , channelModel : Comp.ChannelForm.Model + , formState : FormState + , loading : Int + } + + +type FormState + = FormStateInitial + | FormStateHttpError Http.Error + | FormStateInvalid ValidateError + + +type ValidateError + = ValidateCalEventInvalid + | ValidateQueryStringRequired + | ValidateChannelRequired + + +type Action + = SubmitAction PeriodicQuerySettings + | StartOnceAction PeriodicQuerySettings + | CancelAction + | DeleteAction String + | NoAction + + +type Msg + = Submit + | ToggleEnabled + | CalEventMsg Comp.CalEventInput.Msg + | QueryMsg Comp.PowerSearchInput.Msg + | ChannelMsg Comp.ChannelForm.Msg + | StartOnce + | Cancel + | RequestDelete + | SetSummary String + + +initWith : Flags -> PeriodicQuerySettings -> ( Model, Cmd Msg ) +initWith flags s = + let + newSchedule = + Data.CalEvent.fromEvent s.schedule + |> Maybe.withDefault Data.CalEvent.everyMonth + + ( sm, sc ) = + Comp.CalEventInput.init flags newSchedule + + res = + Comp.PowerSearchInput.update + (Comp.PowerSearchInput.setSearchString s.query) + Comp.PowerSearchInput.init + + ( cfm, cfc ) = + Comp.ChannelForm.initWith flags s.channel + in + ( { settings = s + , enabled = s.enabled + , schedule = Just newSchedule + , scheduleModel = sm + , queryModel = res.model + , channelModel = cfm + , formState = FormStateInitial + , loading = 0 + , summary = s.summary + } + , Cmd.batch + [ Cmd.map CalEventMsg sc + , Cmd.map QueryMsg res.cmd + , Cmd.map ChannelMsg cfc + ] + ) + + +init : Flags -> ChannelType -> ( Model, Cmd Msg ) +init flags ct = + let + initialSchedule = + Data.CalEvent.everyMonth + + ( sm, scmd ) = + Comp.CalEventInput.init flags initialSchedule + + ( cfm, cfc ) = + Comp.ChannelForm.init flags ct + in + ( { settings = Data.PeriodicQuerySettings.empty ct + , enabled = False + , schedule = Just initialSchedule + , scheduleModel = sm + , queryModel = Comp.PowerSearchInput.init + , channelModel = cfm + , formState = FormStateInitial + , loading = 0 + , summary = Nothing + } + , Cmd.batch + [ Cmd.map CalEventMsg scmd + , Cmd.map ChannelMsg cfc + ] + ) + + + +--- Update + + +type alias UpdateResult = + { model : Model + , action : Action + , cmd : Cmd Msg + , sub : Sub Msg + } + + +makeSettings : Model -> Result ValidateError PeriodicQuerySettings +makeSettings model = + let + prev = + model.settings + + schedule_ = + case model.schedule of + Just s -> + Ok s + + Nothing -> + Err ValidateCalEventInvalid + + queryString = + Result.fromMaybe ValidateQueryStringRequired model.queryModel.input + + channelM = + Result.fromMaybe + ValidateChannelRequired + (Comp.ChannelForm.getChannel model.channelModel) + + make timer channel query = + { prev + | enabled = model.enabled + , schedule = Data.CalEvent.makeEvent timer + , summary = model.summary + , channel = channel + , query = query + } + in + Result.map3 make + schedule_ + channelM + queryString + + +withValidSettings : (PeriodicQuerySettings -> Action) -> Model -> UpdateResult +withValidSettings mkcmd model = + case makeSettings model of + Ok set -> + { model = { model | formState = FormStateInitial } + , action = mkcmd set + , cmd = Cmd.none + , sub = Sub.none + } + + Err errs -> + { model = { model | formState = FormStateInvalid errs } + , action = NoAction + , cmd = Cmd.none + , sub = Sub.none + } + + +update : Flags -> Msg -> Model -> UpdateResult +update flags msg model = + case msg of + CalEventMsg lmsg -> + let + ( cm, cc, cs ) = + Comp.CalEventInput.update flags + model.schedule + lmsg + model.scheduleModel + in + { model = + { model + | schedule = cs + , scheduleModel = cm + , formState = FormStateInitial + } + , action = NoAction + , cmd = Cmd.map CalEventMsg cc + , sub = Sub.none + } + + QueryMsg lm -> + let + res = + Comp.PowerSearchInput.update lm model.queryModel + in + { model = { model | queryModel = res.model } + , action = NoAction + , cmd = Cmd.map QueryMsg res.cmd + , sub = Sub.map QueryMsg res.subs + } + + ChannelMsg lm -> + let + ( cfm, cfc ) = + Comp.ChannelForm.update flags lm model.channelModel + in + { model = { model | channelModel = cfm } + , action = NoAction + , cmd = Cmd.map ChannelMsg cfc + , sub = Sub.none + } + + ToggleEnabled -> + { model = + { model + | enabled = not model.enabled + , formState = FormStateInitial + } + , action = NoAction + , cmd = Cmd.none + , sub = Sub.none + } + + Submit -> + withValidSettings + SubmitAction + model + + StartOnce -> + withValidSettings + StartOnceAction + model + + Cancel -> + { model = model + , action = CancelAction + , cmd = Cmd.none + , sub = Sub.none + } + + RequestDelete -> + { model = model + , action = NoAction + , cmd = Cmd.none + , sub = Sub.none + } + + SetSummary str -> + { model = { model | summary = Util.Maybe.fromString str } + , action = NoAction + , cmd = Cmd.none + , sub = Sub.none + } + + + +--- View2 + + +isFormError : Model -> Bool +isFormError model = + case model.formState of + FormStateInitial -> + False + + _ -> + True + + +isFormSuccess : Model -> Bool +isFormSuccess model = + not (isFormError model) + + +view : Texts -> String -> UiSettings -> Model -> Html Msg +view texts extraClasses settings model = + let + startOnceBtn = + MB.SecondaryButton + { tagger = StartOnce + , label = texts.startOnce + , title = texts.startTaskNow + , icon = Just "fa fa-play" + } + + queryInput = + div + [ class "relative flex flex-grow flex-row" ] + [ Html.map QueryMsg + (Comp.PowerSearchInput.viewInput + { placeholder = texts.queryLabel + , extraAttrs = [] + } + model.queryModel + ) + , Html.map QueryMsg + (Comp.PowerSearchInput.viewResult [] model.queryModel) + ] + + formHeader txt = + h2 [ class S.formHeader, class "mt-2" ] + [ text txt + ] + in + div + [ class "flex flex-col md:relative" + , class extraClasses + ] + [ B.loadingDimmer + { active = model.loading > 0 + , label = texts.basics.loading + } + , MB.view + { start = + [ MB.PrimaryButton + { tagger = Submit + , label = texts.basics.submit + , title = texts.basics.submitThisForm + , icon = Just "fa fa-save" + } + , MB.SecondaryButton + { tagger = Cancel + , label = texts.basics.backToList + , title = texts.basics.backToList + , icon = Just "fa fa-arrow-left" + } + ] + , end = + if model.settings.id /= "" then + [ startOnceBtn + , MB.DeleteButton + { tagger = RequestDelete + , label = texts.basics.delete + , title = texts.deleteThisTask + , icon = Just "fa fa-trash" + } + ] + + else + [ startOnceBtn + ] + , rootClasses = "mb-4" + } + , div + [ classList + [ ( S.successMessage, isFormSuccess model ) + , ( S.errorMessage, isFormError model ) + , ( "hidden", model.formState == FormStateInitial ) + ] + , class "mb-4" + ] + [ case model.formState of + FormStateInitial -> + text "" + + FormStateHttpError err -> + text (texts.httpError err) + + FormStateInvalid ValidateCalEventInvalid -> + text texts.invalidCalEvent + + FormStateInvalid ValidateChannelRequired -> + text texts.channelRequired + + FormStateInvalid ValidateQueryStringRequired -> + text texts.queryStringRequired + ] + , div [ class "mb-4" ] + [ MB.viewItem <| + MB.Checkbox + { tagger = \_ -> ToggleEnabled + , label = texts.enableDisable + , value = model.enabled + , id = "notify-enabled" + } + ] + , div [ class "mb-4" ] + [ label [ class S.inputLabel ] + [ text texts.summary + ] + , input + [ type_ "text" + , onInput SetSummary + , class S.textInput + , Maybe.withDefault "" model.summary + |> value + ] + [] + , span [ class "opacity-50 text-sm" ] + [ text texts.summaryInfo + ] + ] + , div [ class "mb-4" ] + [ formHeader (texts.channelHeader (Comp.ChannelForm.channelType model.channelModel)) + , Html.map ChannelMsg + (Comp.ChannelForm.view texts.channelForm settings model.channelModel) + ] + , div [ class "mb-4" ] + [ formHeader texts.queryLabel + , label + [ for "sharequery" + , class S.inputLabel + ] + [ text texts.queryLabel + , B.inputRequired + ] + , queryInput + ] + , div [ class "mb-4" ] + [ formHeader texts.schedule + , label [ class S.inputLabel ] + [ text texts.schedule + , B.inputRequired + , a + [ class "float-right" + , class S.link + , href "https://github.com/eikek/calev#what-are-calendar-events" + , target "_blank" + ] + [ i [ class "fa fa-question" ] [] + , span [ class "pl-2" ] + [ text texts.scheduleClickForHelp + ] + ] + ] + , Html.map CalEventMsg + (Comp.CalEventInput.view2 + texts.calEventInput + "" + model.schedule + model.scheduleModel + ) + , span [ class "opacity-50 text-sm" ] + [ text texts.scheduleInfo + ] + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskList.elm b/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskList.elm new file mode 100644 index 00000000..f654d11e --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskList.elm @@ -0,0 +1,102 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.PeriodicQueryTaskList exposing + ( Action(..) + , Model + , Msg + , init + , update + , view2 + ) + +import Comp.Basic as B +import Data.ChannelType +import Data.NotificationChannel +import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings) +import Html exposing (..) +import Html.Attributes exposing (..) +import Messages.Comp.PeriodicQueryTaskList exposing (Texts) +import Styles as S +import Util.Html + + +type alias Model = + {} + + +type Msg + = EditSettings PeriodicQuerySettings + + +type Action + = NoAction + | EditAction PeriodicQuerySettings + + +init : Model +init = + {} + + +update : Msg -> Model -> ( Model, Action ) +update msg model = + case msg of + EditSettings settings -> + ( model, EditAction settings ) + + + +--- View2 + + +view2 : Texts -> Model -> List PeriodicQuerySettings -> Html Msg +view2 texts _ items = + div [] + [ table [ class S.tableMain ] + [ thead [] + [ tr [] + [ th [ class "" ] [] + , th [ class "text-center mr-2" ] + [ i [ class "fa fa-check" ] [] + ] + , th [ class "text-left " ] [ text texts.summary ] + , th [ class "text-left hidden sm:table-cell mr-2" ] + [ text texts.schedule ] + , th [ class "text-left mr-2" ] + [ text texts.connection ] + ] + ] + , tbody [] + (List.map (viewItem2 texts) items) + ] + ] + + +viewItem2 : Texts -> PeriodicQuerySettings -> Html Msg +viewItem2 texts item = + tr [] + [ B.editLinkTableCell texts.basics.edit (EditSettings item) + , td [ class "w-px whitespace-nowrap px-2 text-center" ] + [ Util.Html.checkbox2 item.enabled + ] + , td [ class "text-left" ] + [ Maybe.withDefault "" item.summary + |> text + ] + , td [ class "text-left hidden sm:table-cell mr-2" ] + [ code [ class "font-mono text-sm" ] + [ text item.schedule + ] + ] + , td [ class "text-left py-4 md:py-2" ] + [ Data.NotificationChannel.channelType item.channel + |> Maybe.map Data.ChannelType.asString + |> Maybe.withDefault "-" + |> text + ] + ] diff --git a/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskManage.elm b/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskManage.elm new file mode 100644 index 00000000..973557e4 --- /dev/null +++ b/modules/webapp/src/main/elm/Comp/PeriodicQueryTaskManage.elm @@ -0,0 +1,324 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Comp.PeriodicQueryTaskManage exposing + ( Model + , Msg + , init + , update + , view + ) + +import Api +import Api.Model.BasicResult exposing (BasicResult) +import Comp.ChannelMenu +import Comp.MenuBar as MB +import Comp.PeriodicQueryTaskForm +import Comp.PeriodicQueryTaskList +import Data.ChannelType exposing (ChannelType) +import Data.Flags exposing (Flags) +import Data.PeriodicQuerySettings exposing (PeriodicQuerySettings) +import Data.UiSettings exposing (UiSettings) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick) +import Http +import Messages.Comp.PeriodicQueryTaskManage exposing (Texts) +import Styles as S + + +type alias Model = + { listModel : Comp.PeriodicQueryTaskList.Model + , detailModel : Maybe Comp.PeriodicQueryTaskForm.Model + , items : List PeriodicQuerySettings + , formState : FormState + , channelMenuOpen : Bool + } + + +type SubmitType + = SubmitDelete + | SubmitUpdate + | SubmitCreate + | SubmitStartOnce + + +type FormState + = FormStateInitial + | FormHttpError Http.Error + | FormSubmitSuccessful SubmitType + | FormSubmitFailed String + + +type Msg + = ListMsg Comp.PeriodicQueryTaskList.Msg + | DetailMsg Comp.PeriodicQueryTaskForm.Msg + | GetDataResp (Result Http.Error (List PeriodicQuerySettings)) + | NewTaskInit ChannelType + | SubmitResp SubmitType (Result Http.Error BasicResult) + | ToggleChannelMenu + + +initModel : Model +initModel = + { listModel = Comp.PeriodicQueryTaskList.init + , detailModel = Nothing + , items = [] + , formState = FormStateInitial + , channelMenuOpen = False + } + + +initCmd : Flags -> Cmd Msg +initCmd flags = + Api.getPeriodicQuery flags GetDataResp + + +init : Flags -> ( Model, Cmd Msg ) +init flags = + ( initModel, initCmd flags ) + + + +--- Update + + +update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) +update flags msg model = + case msg of + GetDataResp (Ok items) -> + ( { model + | items = items + , formState = FormStateInitial + } + , Cmd.none + , Sub.none + ) + + GetDataResp (Err err) -> + ( { model | formState = FormHttpError err } + , Cmd.none + , Sub.none + ) + + ListMsg lm -> + let + ( mm, action ) = + Comp.PeriodicQueryTaskList.update lm model.listModel + + ( detail, cmd ) = + case action of + Comp.PeriodicQueryTaskList.NoAction -> + ( Nothing, Cmd.none ) + + Comp.PeriodicQueryTaskList.EditAction settings -> + let + ( dm, dc ) = + Comp.PeriodicQueryTaskForm.initWith flags settings + in + ( Just dm, Cmd.map DetailMsg dc ) + in + ( { model + | listModel = mm + , detailModel = detail + } + , cmd + , Sub.none + ) + + DetailMsg lm -> + case model.detailModel of + Just dm -> + let + --( mm, action, mc ) = + result = + Comp.PeriodicQueryTaskForm.update flags lm dm + + ( model_, cmd_ ) = + case result.action of + Comp.PeriodicQueryTaskForm.NoAction -> + ( { model + | detailModel = Just result.model + , formState = FormStateInitial + } + , Cmd.none + ) + + Comp.PeriodicQueryTaskForm.SubmitAction settings -> + ( { model + | detailModel = Just result.model + , formState = FormStateInitial + } + , if settings.id == "" then + Api.createPeriodicQuery flags settings (SubmitResp SubmitCreate) + + else + Api.updatePeriodicQuery flags settings (SubmitResp SubmitUpdate) + ) + + Comp.PeriodicQueryTaskForm.CancelAction -> + ( { model + | detailModel = Nothing + , formState = FormStateInitial + } + , initCmd flags + ) + + Comp.PeriodicQueryTaskForm.StartOnceAction settings -> + ( { model + | detailModel = Just result.model + , formState = FormStateInitial + } + , Api.startOncePeriodicQuery flags settings (SubmitResp SubmitStartOnce) + ) + + Comp.PeriodicQueryTaskForm.DeleteAction id -> + ( { model + | detailModel = Just result.model + , formState = FormStateInitial + } + , Api.deletePeriodicQueryTask flags id (SubmitResp SubmitDelete) + ) + in + ( model_ + , Cmd.batch + [ Cmd.map DetailMsg result.cmd + , cmd_ + ] + , Sub.map DetailMsg result.sub + ) + + Nothing -> + ( model, Cmd.none, Sub.none ) + + NewTaskInit ct -> + let + ( mm, mc ) = + Comp.PeriodicQueryTaskForm.init flags ct + in + ( { model | detailModel = Just mm, channelMenuOpen = False }, Cmd.map DetailMsg mc, Sub.none ) + + SubmitResp submitType (Ok res) -> + ( { model + | formState = + if res.success then + FormSubmitSuccessful submitType + + else + FormSubmitFailed res.message + , detailModel = + if submitType == SubmitDelete then + Nothing + + else + model.detailModel + } + , if submitType == SubmitDelete then + initCmd flags + + else + Cmd.none + , Sub.none + ) + + SubmitResp _ (Err err) -> + ( { model | formState = FormHttpError err } + , Cmd.none + , Sub.none + ) + + ToggleChannelMenu -> + ( { model | channelMenuOpen = not model.channelMenuOpen }, Cmd.none, Sub.none ) + + + +--- View2 + + +view : Texts -> UiSettings -> Model -> Html Msg +view texts settings model = + div [ class "flex flex-col" ] + (div + [ classList + [ ( S.errorMessage, model.formState /= FormStateInitial ) + , ( S.successMessage, isSuccess model.formState ) + , ( "hidden", model.formState == FormStateInitial ) + ] + , class "mb-2" + ] + [ case model.formState of + FormStateInitial -> + text "" + + FormSubmitSuccessful SubmitCreate -> + text texts.taskCreated + + FormSubmitSuccessful SubmitUpdate -> + text texts.taskUpdated + + FormSubmitSuccessful SubmitStartOnce -> + text texts.taskStarted + + FormSubmitSuccessful SubmitDelete -> + text texts.taskDeleted + + FormSubmitFailed m -> + text m + + FormHttpError err -> + text (texts.httpError err) + ] + :: (case model.detailModel of + Just msett -> + viewForm2 texts settings msett + + Nothing -> + viewList2 texts model + ) + ) + + +isSuccess : FormState -> Bool +isSuccess state = + case state of + FormSubmitSuccessful _ -> + True + + _ -> + False + + +viewForm2 : Texts -> UiSettings -> Comp.PeriodicQueryTaskForm.Model -> List (Html Msg) +viewForm2 texts settings model = + [ Html.map DetailMsg + (Comp.PeriodicQueryTaskForm.view texts.notificationForm "flex flex-col" settings model) + ] + + +viewList2 : Texts -> Model -> List (Html Msg) +viewList2 texts model = + let + menuModel = + { menuOpen = model.channelMenuOpen + , toggleMenu = ToggleChannelMenu + , menuLabel = texts.newTask + , onItem = NewTaskInit + } + in + [ MB.view + { start = [] + , end = + [ Comp.ChannelMenu.channelMenu texts.channelType menuModel + ] + , rootClasses = "mb-4" + } + , Html.map ListMsg + (Comp.PeriodicQueryTaskList.view2 texts.notificationTable + model.listModel + model.items + ) + ] diff --git a/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm b/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm index 2a10827e..51af73b4 100644 --- a/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm +++ b/modules/webapp/src/main/elm/Comp/ScanMailboxManage.elm @@ -287,7 +287,8 @@ viewForm2 texts flags settings model = viewList2 : Texts -> Model -> List (Html Msg) viewList2 texts model = [ MB.view - { start = + { start = [] + , end = [ MB.PrimaryButton { tagger = NewTask , label = texts.newTask @@ -295,7 +296,6 @@ viewList2 texts model = , title = texts.createNewTask } ] - , end = [] , rootClasses = "mb-4" } , Html.map ListMsg diff --git a/modules/webapp/src/main/elm/Data/ChannelRef.elm b/modules/webapp/src/main/elm/Data/ChannelRef.elm new file mode 100644 index 00000000..4c69cb74 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/ChannelRef.elm @@ -0,0 +1,33 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Data.ChannelRef exposing (..) + +import Data.ChannelType exposing (ChannelType) +import Json.Decode as D +import Json.Encode as E + + +type alias ChannelRef = + { id : String + , channelType : ChannelType + } + + +decoder : D.Decoder ChannelRef +decoder = + D.map2 ChannelRef + (D.field "id" D.string) + (D.field "channelType" Data.ChannelType.decoder) + + +encode : ChannelRef -> E.Value +encode cref = + E.object + [ ( "id", E.string cref.id ) + , ( "channelType", Data.ChannelType.encode cref.channelType ) + ] diff --git a/modules/webapp/src/main/elm/Data/ChannelType.elm b/modules/webapp/src/main/elm/Data/ChannelType.elm new file mode 100644 index 00000000..5e35dc64 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/ChannelType.elm @@ -0,0 +1,117 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Data.ChannelType exposing + ( ChannelType(..) + , all + , asString + , decoder + , encode + , fromString + , icon + ) + +import Data.Icons as Icons +import Html exposing (Html, i) +import Html.Attributes exposing (class) +import Json.Decode as D +import Json.Encode as E + + +type ChannelType + = Mail + | Gotify + | Matrix + | Http + + +all : List ChannelType +all = + [ Matrix + , Gotify + , Mail + , Http + ] + + +fromString : String -> Maybe ChannelType +fromString str = + case String.toLower str of + "mail" -> + Just Mail + + "matrix" -> + Just Matrix + + "gotify" -> + Just Gotify + + "http" -> + Just Http + + _ -> + Nothing + + +asString : ChannelType -> String +asString et = + case et of + Mail -> + "Mail" + + Matrix -> + "Matrix" + + Gotify -> + "Gotify" + + Http -> + "Http" + + +decoder : D.Decoder ChannelType +decoder = + let + unwrap me = + case me of + Just et -> + D.succeed et + + Nothing -> + D.fail "Unknown event type!" + in + D.map fromString D.string + |> D.andThen unwrap + + +encode : ChannelType -> E.Value +encode et = + E.string (asString et) + + +icon : ChannelType -> String -> Html msg +icon ct classes = + case ct of + Matrix -> + Icons.matrixIcon classes + + Mail -> + i + [ class "fa fa-envelope" + , class classes + ] + [] + + Gotify -> + Icons.gotifyIcon classes + + Http -> + i + [ class "fa fa-ethernet" + , class classes + ] + [] diff --git a/modules/webapp/src/main/elm/Data/EventType.elm b/modules/webapp/src/main/elm/Data/EventType.elm new file mode 100644 index 00000000..aac892a2 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/EventType.elm @@ -0,0 +1,90 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Data.EventType exposing (..) + +import Json.Decode as D +import Json.Encode as E + + +type EventType + = TagsChanged + | SetFieldValue + | DeleteFieldValue + | JobSubmitted + | JobDone + + +all : List EventType +all = + [ TagsChanged + , SetFieldValue + , DeleteFieldValue + , JobSubmitted + , JobDone + ] + + +fromString : String -> Maybe EventType +fromString str = + case String.toLower str of + "tagschanged" -> + Just TagsChanged + + "setfieldvalue" -> + Just SetFieldValue + + "deletefieldvalue" -> + Just DeleteFieldValue + + "jobsubmitted" -> + Just JobSubmitted + + "jobdone" -> + Just JobDone + + _ -> + Nothing + + +asString : EventType -> String +asString et = + case et of + TagsChanged -> + "TagsChanged" + + SetFieldValue -> + "SetFieldValue" + + DeleteFieldValue -> + "DeleteFieldValue" + + JobSubmitted -> + "JobSubmitted" + + JobDone -> + "JobDone" + + +decoder : D.Decoder EventType +decoder = + let + unwrap me = + case me of + Just et -> + D.succeed et + + Nothing -> + D.fail "Unknown event type!" + in + D.map fromString D.string + |> D.andThen unwrap + + +encode : EventType -> E.Value +encode et = + E.string (asString et) diff --git a/modules/webapp/src/main/elm/Data/Icons.elm b/modules/webapp/src/main/elm/Data/Icons.elm index dbe79fc0..6bc0aeb1 100644 --- a/modules/webapp/src/main/elm/Data/Icons.elm +++ b/modules/webapp/src/main/elm/Data/Icons.elm @@ -47,7 +47,9 @@ module Data.Icons exposing , folder2 , folderIcon , folderIcon2 + , gotifyIcon , itemDatesIcon + , matrixIcon , organization , organization2 , organizationIcon @@ -73,8 +75,10 @@ module Data.Icons exposing ) import Data.CustomFieldType exposing (CustomFieldType) -import Html exposing (Html, i) -import Html.Attributes exposing (class) +import Html exposing (Html, i, img) +import Html.Attributes exposing (class, src) +import Svg +import Svg.Attributes as SA share : String @@ -447,3 +451,32 @@ equipmentIcon classes = equipmentIcon2 : String -> Html msg equipmentIcon2 classes = i [ class (equipment2 ++ " " ++ classes) ] [] + + +matrixIcon : String -> Html msg +matrixIcon classes = + Svg.svg + [ SA.width "520" + , SA.height "520" + , SA.viewBox "0 0 520 520" + , SA.class classes + ] + [ Svg.path + [ SA.d "M13.7,11.9v496.2h35.7V520H0V0h49.4v11.9H13.7z" ] + [] + , Svg.path + [ SA.d "M166.3,169.2v25.1h0.7c6.7-9.6,14.8-17,24.2-22.2c9.4-5.3,20.3-7.9,32.5-7.9c11.7,0,22.4,2.3,32.1,6.8\n\tc9.7,4.5,17,12.6,22.1,24c5.5-8.1,13-15.3,22.4-21.5c9.4-6.2,20.6-9.3,33.5-9.3c9.8,0,18.9,1.2,27.3,3.6c8.4,2.4,15.5,6.2,21.5,11.5\n\tc6,5.3,10.6,12.1,14,20.6c3.3,8.5,5,18.7,5,30.7v124.1h-50.9V249.6c0-6.2-0.2-12.1-0.7-17.6c-0.5-5.5-1.8-10.3-3.9-14.3\n\tc-2.2-4.1-5.3-7.3-9.5-9.7c-4.2-2.4-9.9-3.6-17-3.6c-7.2,0-13,1.4-17.4,4.1c-4.4,2.8-7.9,6.3-10.4,10.8c-2.5,4.4-4.2,9.4-5,15.1\n\tc-0.8,5.6-1.3,11.3-1.3,17v103.3h-50.9v-104c0-5.5-0.1-10.9-0.4-16.3c-0.2-5.4-1.3-10.3-3.1-14.9c-1.8-4.5-4.8-8.2-9-10.9\n\tc-4.2-2.7-10.3-4.1-18.5-4.1c-2.4,0-5.6,0.5-9.5,1.6c-3.9,1.1-7.8,3.1-11.5,6.1c-3.7,3-6.9,7.3-9.5,12.9c-2.6,5.6-3.9,13-3.9,22.1\n\tv107.6h-50.9V169.2H166.3z" ] + [] + , Svg.path + [ SA.d "M506.3,508.1V11.9h-35.7V0H520v520h-49.4v-11.9H506.3z" ] + [] + ] + + +gotifyIcon : String -> Html msg +gotifyIcon classes = + img + [ class classes + , src "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC80lEQVQ4y32SW0iTYRjHh7WL6K4gCKILbwQzJeomQcKLKEtJvAo0M8vDPG+WFlagaKgdzYgiUYRSUuzCwMN0NtOJ29xJN+fUj3nKedhe9+mOmvv3ft+FZlkPPHwvfO//x/P8379AQOtUXOL70/HJjcFRl4tDr14vC7mY8PDEmchbh48eO0t/HxT8ry6IK9pEvQwKtRsoGvOj2LjJ9z29G9nyOcS/aB49HnYu+Z+AYtOWlxOL1WsQqwj/LRhZR46aRb7WhfsTARSOsAhPSKndF0BFDl7INb2Y8d2Gwi4jnkh1KO3WI0s6BbHOTaEsYlJzW6Iiz6fsD6AXRDIrWgd1WHPYgZ+b2PZ5oDNPIr/TiDydBw8G5+Ega4iLjb37FyBTsYJ6uQZAAH+WTGNEunwBaQPL+GZZgLxX6qfSkF3AiBOiHgYW69yOKBAIQKlUYnFxERssCwldK0vrQc3ABOaYSa9QKDy5A+D2y5Va8GNpeQfg8/kQHR2N+vp6StvGI/kUbraPQ1z+ElVV1eagoKBDuxOoncjotUJnYfaMbrVaQQjB8qodonY9nja8Q93rUlQ+zrQJhQeO7PEgW7mG8i4NNXB1D8TvdqFGpkdquwHyr69gGapD3p1rTX+ZKKHvnzVkR1GHHh8HDejUmvF52IiS7jGkKegEKhbJzQMof/Y8EBEekR4cHBzPp/T3HEiomflaN24PEST1zOFGxyRyuswoo5N9kKnRqRqFyTyB+fl59Pf3Iyw0RCQQKx0O2vwE2YpV5HZbUCnV41P/CIb0RszOWMHaV+DbYPl1OHM1Gg3vzZWYS+WCfMWSgwtRroxBNWfSmzJ0fWmEZ53Flt8Pl8sFlj6j0+mE2+2GyWTC+Pg4709iYlIFB2C5/OcN2yFp60NTSwMM2mGoVGoYDAbYbDZ4PB54vV7MzMxAoVDwZ65KSkpaBQXDdobuTyiEZCg3yNs+Pdn2esj6OktmZ2eJWq0mMpmMMAxDqJjv6elpQoNGamtr+34BzIywNQI18UAAAAAASUVORK5CYII=" + ] + [] diff --git a/modules/webapp/src/main/elm/Data/NotificationChannel.elm b/modules/webapp/src/main/elm/Data/NotificationChannel.elm new file mode 100644 index 00000000..643cac06 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/NotificationChannel.elm @@ -0,0 +1,148 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Data.NotificationChannel exposing + ( NotificationChannel(..) + , asString + , channelType + , decoder + , empty + , encode + , setTypeGotify + , setTypeHttp + , setTypeMail + , setTypeMatrix + ) + +import Api.Model.NotificationGotify exposing (NotificationGotify) +import Api.Model.NotificationHttp exposing (NotificationHttp) +import Api.Model.NotificationMail exposing (NotificationMail) +import Api.Model.NotificationMatrix exposing (NotificationMatrix) +import Data.ChannelRef exposing (ChannelRef) +import Data.ChannelType exposing (ChannelType) +import Json.Decode as D +import Json.Encode as E + + +type NotificationChannel + = Matrix NotificationMatrix + | Mail NotificationMail + | Gotify NotificationGotify + | Http NotificationHttp + | Ref ChannelRef + + +empty : ChannelType -> NotificationChannel +empty ct = + let + set = + setType ct + in + case ct of + Data.ChannelType.Mail -> + Mail <| set Api.Model.NotificationMail.empty + + Data.ChannelType.Matrix -> + Matrix <| set Api.Model.NotificationMatrix.empty + + Data.ChannelType.Gotify -> + Gotify <| set Api.Model.NotificationGotify.empty + + Data.ChannelType.Http -> + Http <| set Api.Model.NotificationHttp.empty + + +setType ct rec = + { rec | channelType = Data.ChannelType.asString ct } + + +setTypeHttp : NotificationHttp -> NotificationHttp +setTypeHttp h = + setType Data.ChannelType.Http h + + +setTypeMail : NotificationMail -> NotificationMail +setTypeMail h = + setType Data.ChannelType.Mail h + + +setTypeMatrix : NotificationMatrix -> NotificationMatrix +setTypeMatrix h = + setType Data.ChannelType.Matrix h + + +setTypeGotify : NotificationGotify -> NotificationGotify +setTypeGotify h = + setType Data.ChannelType.Gotify h + + +decoder : D.Decoder NotificationChannel +decoder = + D.oneOf + [ D.map Gotify Api.Model.NotificationGotify.decoder + , D.map Mail Api.Model.NotificationMail.decoder + , D.map Matrix Api.Model.NotificationMatrix.decoder + , D.map Http Api.Model.NotificationHttp.decoder + , D.map Ref Data.ChannelRef.decoder + ] + + +encode : NotificationChannel -> E.Value +encode channel = + case channel of + Matrix ch -> + Api.Model.NotificationMatrix.encode ch + + Mail ch -> + Api.Model.NotificationMail.encode ch + + Gotify ch -> + Api.Model.NotificationGotify.encode ch + + Http ch -> + Api.Model.NotificationHttp.encode ch + + Ref ch -> + Data.ChannelRef.encode ch + + +channelType : NotificationChannel -> Maybe ChannelType +channelType ch = + case ch of + Matrix m -> + Data.ChannelType.fromString m.channelType + + Mail m -> + Data.ChannelType.fromString m.channelType + + Gotify m -> + Data.ChannelType.fromString m.channelType + + Http m -> + Data.ChannelType.fromString m.channelType + + Ref m -> + Just m.channelType + + +asString : NotificationChannel -> String +asString channel = + case channel of + Matrix ch -> + "Matrix @ " ++ ch.homeServer ++ "(" ++ ch.roomId ++ ")" + + Mail ch -> + "Mail @ " ++ ch.connection ++ " (" ++ String.join ", " ch.recipients ++ ")" + + Gotify ch -> + "Gotify @ " ++ ch.url + + Http ch -> + "Http @ " ++ ch.url + + Ref ch -> + "Ref(" ++ Data.ChannelType.asString ch.channelType ++ "/" ++ ch.id ++ ")" diff --git a/modules/webapp/src/main/elm/Data/NotificationHook.elm b/modules/webapp/src/main/elm/Data/NotificationHook.elm new file mode 100644 index 00000000..91c53b60 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/NotificationHook.elm @@ -0,0 +1,62 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Data.NotificationHook exposing (NotificationHook, decoder, empty, encode) + +import Data.ChannelType exposing (ChannelType) +import Data.EventType exposing (EventType) +import Data.NotificationChannel exposing (NotificationChannel) +import Json.Decode as D +import Json.Encode as E + + +type alias NotificationHook = + { id : String + , enabled : Bool + , channel : NotificationChannel + , allEvents : Bool + , eventFilter : Maybe String + , events : List EventType + } + + +empty : ChannelType -> NotificationHook +empty ct = + { id = "" + , enabled = True + , channel = Data.NotificationChannel.empty ct + , allEvents = False + , eventFilter = Nothing + , events = [] + } + + +decoder : D.Decoder NotificationHook +decoder = + D.map6 NotificationHook + (D.field "id" D.string) + (D.field "enabled" D.bool) + (D.field "channel" Data.NotificationChannel.decoder) + (D.field "allEvents" D.bool) + (D.field "eventFilter" (D.maybe D.string)) + (D.field "events" (D.list Data.EventType.decoder)) + + +encode : NotificationHook -> E.Value +encode hook = + E.object + [ ( "id", E.string hook.id ) + , ( "enabled", E.bool hook.enabled ) + , ( "channel", Data.NotificationChannel.encode hook.channel ) + , ( "allEvents", E.bool hook.allEvents ) + , ( "eventFilter", Maybe.map E.string hook.eventFilter |> Maybe.withDefault E.null ) + , ( "events", E.list Data.EventType.encode hook.events ) + ] + + + +--- private diff --git a/modules/webapp/src/main/elm/Data/PeriodicDueItemsSettings.elm b/modules/webapp/src/main/elm/Data/PeriodicDueItemsSettings.elm new file mode 100644 index 00000000..d1058d18 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/PeriodicDueItemsSettings.elm @@ -0,0 +1,77 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Data.PeriodicDueItemsSettings exposing (..) + +import Api.Model.Tag exposing (Tag) +import Data.ChannelType exposing (ChannelType) +import Data.NotificationChannel exposing (NotificationChannel) +import Json.Decode as Decode +import Json.Decode.Pipeline as P +import Json.Encode as Encode + + + +{-- + - Settings for notifying about due items. + --} + + +type alias PeriodicDueItemsSettings = + { id : String + , enabled : Bool + , summary : Maybe String + , channel : NotificationChannel + , schedule : String + , remindDays : Int + , capOverdue : Bool + , tagsInclude : List Tag + , tagsExclude : List Tag + } + + +empty : ChannelType -> PeriodicDueItemsSettings +empty ct = + { id = "" + , enabled = False + , summary = Nothing + , channel = Data.NotificationChannel.empty ct + , schedule = "" + , remindDays = 0 + , capOverdue = False + , tagsInclude = [] + , tagsExclude = [] + } + + +decoder : Decode.Decoder PeriodicDueItemsSettings +decoder = + Decode.succeed PeriodicDueItemsSettings + |> P.required "id" Decode.string + |> P.required "enabled" Decode.bool + |> P.optional "summary" (Decode.maybe Decode.string) Nothing + |> P.required "channel" Data.NotificationChannel.decoder + |> P.required "schedule" Decode.string + |> P.required "remindDays" Decode.int + |> P.required "capOverdue" Decode.bool + |> P.required "tagsInclude" (Decode.list Api.Model.Tag.decoder) + |> P.required "tagsExclude" (Decode.list Api.Model.Tag.decoder) + + +encode : PeriodicDueItemsSettings -> Encode.Value +encode value = + Encode.object + [ ( "id", Encode.string value.id ) + , ( "enabled", Encode.bool value.enabled ) + , ( "summary", (Maybe.map Encode.string >> Maybe.withDefault Encode.null) value.summary ) + , ( "channel", Data.NotificationChannel.encode value.channel ) + , ( "schedule", Encode.string value.schedule ) + , ( "remindDays", Encode.int value.remindDays ) + , ( "capOverdue", Encode.bool value.capOverdue ) + , ( "tagsInclude", Encode.list Api.Model.Tag.encode value.tagsInclude ) + , ( "tagsExclude", Encode.list Api.Model.Tag.encode value.tagsExclude ) + ] diff --git a/modules/webapp/src/main/elm/Data/PeriodicQuerySettings.elm b/modules/webapp/src/main/elm/Data/PeriodicQuerySettings.elm new file mode 100644 index 00000000..63db0087 --- /dev/null +++ b/modules/webapp/src/main/elm/Data/PeriodicQuerySettings.elm @@ -0,0 +1,57 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Data.PeriodicQuerySettings exposing (PeriodicQuerySettings, decoder, empty, encode) + +import Data.ChannelType exposing (ChannelType) +import Data.NotificationChannel exposing (NotificationChannel) +import Json.Decode as D +import Json.Encode as E + + +type alias PeriodicQuerySettings = + { id : String + , enabled : Bool + , summary : Maybe String + , channel : NotificationChannel + , query : String + , schedule : String + } + + +empty : ChannelType -> PeriodicQuerySettings +empty ct = + { id = "" + , enabled = False + , summary = Nothing + , channel = Data.NotificationChannel.empty ct + , query = "" + , schedule = "" + } + + +decoder : D.Decoder PeriodicQuerySettings +decoder = + D.map6 PeriodicQuerySettings + (D.field "id" D.string) + (D.field "enabled" D.bool) + (D.field "summary" (D.maybe D.string)) + (D.field "channel" Data.NotificationChannel.decoder) + (D.field "query" D.string) + (D.field "schedule" D.string) + + +encode : PeriodicQuerySettings -> E.Value +encode s = + E.object + [ ( "id", E.string s.id ) + , ( "enabled", E.bool s.enabled ) + , ( "summary", Maybe.map E.string s.summary |> Maybe.withDefault E.null ) + , ( "channel", Data.NotificationChannel.encode s.channel ) + , ( "query", E.string s.query ) + , ( "schedule", E.string s.schedule ) + ] diff --git a/modules/webapp/src/main/elm/Main.elm b/modules/webapp/src/main/elm/Main.elm index be94b7ff..3569ad5c 100644 --- a/modules/webapp/src/main/elm/Main.elm +++ b/modules/webapp/src/main/elm/Main.elm @@ -14,6 +14,7 @@ import App.View2 import Browser exposing (Document) import Browser.Navigation exposing (Key) import Data.Flags exposing (Flags) +import Data.NotificationChannel import Data.UiSettings import Html exposing (..) import Html.Attributes exposing (..) diff --git a/modules/webapp/src/main/elm/Messages/Comp/ChannelForm.elm b/modules/webapp/src/main/elm/Messages/Comp/ChannelForm.elm new file mode 100644 index 00000000..fc034814 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/ChannelForm.elm @@ -0,0 +1,47 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.ChannelForm exposing + ( Texts + , de + , gb + ) + +import Messages.Basics +import Messages.Comp.NotificationGotifyForm +import Messages.Comp.NotificationHttpForm +import Messages.Comp.NotificationMailForm +import Messages.Comp.NotificationMatrixForm + + +type alias Texts = + { basics : Messages.Basics.Texts + , matrixForm : Messages.Comp.NotificationMatrixForm.Texts + , gotifyForm : Messages.Comp.NotificationGotifyForm.Texts + , mailForm : Messages.Comp.NotificationMailForm.Texts + , httpForm : Messages.Comp.NotificationHttpForm.Texts + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , matrixForm = Messages.Comp.NotificationMatrixForm.gb + , gotifyForm = Messages.Comp.NotificationGotifyForm.gb + , mailForm = Messages.Comp.NotificationMailForm.gb + , httpForm = Messages.Comp.NotificationHttpForm.gb + } + + +de : Texts +de = + { basics = Messages.Basics.de + , matrixForm = Messages.Comp.NotificationMatrixForm.de + , gotifyForm = Messages.Comp.NotificationGotifyForm.de + , mailForm = Messages.Comp.NotificationMailForm.de + , httpForm = Messages.Comp.NotificationHttpForm.de + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationForm.elm b/modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskForm.elm similarity index 85% rename from modules/webapp/src/main/elm/Messages/Comp/NotificationForm.elm rename to modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskForm.elm index 76f58cd1..48f721e3 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/NotificationForm.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskForm.elm @@ -5,7 +5,7 @@ -} -module Messages.Comp.NotificationForm exposing +module Messages.Comp.DueItemsTaskForm exposing ( Texts , de , gb @@ -14,25 +14,23 @@ module Messages.Comp.NotificationForm exposing import Http import Messages.Basics import Messages.Comp.CalEventInput +import Messages.Comp.ChannelForm import Messages.Comp.HttpError +import Messages.Data.ChannelType type alias Texts = { basics : Messages.Basics.Texts , calEventInput : Messages.Comp.CalEventInput.Texts , httpError : Http.Error -> String + , channelForm : Messages.Comp.ChannelForm.Texts , reallyDeleteTask : String , startOnce : String , startTaskNow : String - , selectConnection : String , deleteThisTask : String , enableDisable : String , summary : String , summaryInfo : String - , sendVia : String - , sendViaInfo : String - , recipients : String - , recipientsInfo : String , tagsInclude : String , tagsIncludeInfo : String , tagsExclude : String @@ -48,6 +46,9 @@ type alias Texts = , invalidCalEvent : String , remindDaysRequired : String , recipientsRequired : String + , queryLabel : String + , channelRequired : String + , channelHeader : Messages.Data.ChannelType.Texts } @@ -56,18 +57,14 @@ gb = { basics = Messages.Basics.gb , calEventInput = Messages.Comp.CalEventInput.gb , httpError = Messages.Comp.HttpError.gb + , channelForm = Messages.Comp.ChannelForm.gb , reallyDeleteTask = "Really delete this notification task?" , startOnce = "Start Once" , startTaskNow = "Start this task now" - , selectConnection = "Select connection..." , deleteThisTask = "Delete this task" , enableDisable = "Enable or disable this task." , summary = "Summary" , summaryInfo = "Some human readable name, only for displaying" - , sendVia = "Send via" - , sendViaInfo = "The SMTP connection to use when sending notification mails." - , recipients = "Recipient(s)" - , recipientsInfo = "One or more mail addresses, confirm each by pressing 'Return'." , tagsInclude = "Tags Include (and)" , tagsIncludeInfo = "Items must have all the tags specified here." , tagsExclude = "Tags Exclude (or)" @@ -87,6 +84,9 @@ gb = , invalidCalEvent = "The calendar event is not valid." , remindDaysRequired = "Remind-Days is required." , recipientsRequired = "At least one recipient is required." + , queryLabel = "Query" + , channelRequired = "A valid channel must be given." + , channelHeader = \ct -> "Connection details for " ++ Messages.Data.ChannelType.gb ct } @@ -95,18 +95,14 @@ de = { basics = Messages.Basics.de , calEventInput = Messages.Comp.CalEventInput.de , httpError = Messages.Comp.HttpError.de + , channelForm = Messages.Comp.ChannelForm.gb , reallyDeleteTask = "Diesen Benachrichtigungsauftrag wirklich löschen?" , startOnce = "Jetzt starten" , startTaskNow = "Starte den Auftrag sofort" - , selectConnection = "Verbindung auswählen…" , deleteThisTask = "Den Auftrag löschen" , enableDisable = "Auftrag aktivieren oder deaktivieren" , summary = "Kurzbeschreibung" , summaryInfo = "Eine kurze lesbare Zusammenfassung, nur für die Anzeige" - , sendVia = "Senden via" - , sendViaInfo = "Die SMTP-Verbindung, die zum Senden der Benachrichtigungs-E-Mails verwendet werden soll." - , recipients = "Empfänger" - , recipientsInfo = "Eine oder mehrere E-Mail-Adressen, jede mit 'Eingabe' bestätigen." , tagsInclude = "Tags verknüpft (&&)" , tagsIncludeInfo = "Dokumente müssen alle diese Tags haben." , tagsExclude = "Tags nicht verknüpft (||)" @@ -126,4 +122,7 @@ de = , invalidCalEvent = "Das Kalenderereignis ist nicht gültig." , remindDaysRequired = "'Fällig in Tagen' ist erforderlich." , recipientsRequired = "Mindestens ein Empfänger muss angegeben werden." + , queryLabel = "Abfrage" + , channelRequired = "Ein Versandkanal muss angegeben werden." + , channelHeader = \ct -> "Details für " ++ Messages.Data.ChannelType.de ct } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationTable.elm b/modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskList.elm similarity index 93% rename from modules/webapp/src/main/elm/Messages/Comp/NotificationTable.elm rename to modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskList.elm index 3cb48380..3efa4228 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/NotificationTable.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskList.elm @@ -5,7 +5,7 @@ -} -module Messages.Comp.NotificationTable exposing +module Messages.Comp.DueItemsTaskList exposing ( Texts , de , gb diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationManage.elm b/modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskManage.elm similarity index 63% rename from modules/webapp/src/main/elm/Messages/Comp/NotificationManage.elm rename to modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskManage.elm index 36be7bd3..8cdbca7e 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/NotificationManage.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/DueItemsTaskManage.elm @@ -5,7 +5,7 @@ -} -module Messages.Comp.NotificationManage exposing +module Messages.Comp.DueItemsTaskManage exposing ( Texts , de , gb @@ -13,16 +13,18 @@ module Messages.Comp.NotificationManage exposing import Http import Messages.Basics +import Messages.Comp.DueItemsTaskForm +import Messages.Comp.DueItemsTaskList import Messages.Comp.HttpError -import Messages.Comp.NotificationForm -import Messages.Comp.NotificationTable +import Messages.Data.ChannelType type alias Texts = { basics : Messages.Basics.Texts - , notificationForm : Messages.Comp.NotificationForm.Texts - , notificationTable : Messages.Comp.NotificationTable.Texts + , notificationForm : Messages.Comp.DueItemsTaskForm.Texts + , notificationTable : Messages.Comp.DueItemsTaskList.Texts , httpError : Http.Error -> String + , channelType : Messages.Data.ChannelType.Texts , newTask : String , createNewTask : String , taskCreated : String @@ -35,9 +37,10 @@ type alias Texts = gb : Texts gb = { basics = Messages.Basics.gb - , notificationForm = Messages.Comp.NotificationForm.gb - , notificationTable = Messages.Comp.NotificationTable.gb + , notificationForm = Messages.Comp.DueItemsTaskForm.gb + , notificationTable = Messages.Comp.DueItemsTaskList.gb , httpError = Messages.Comp.HttpError.gb + , channelType = Messages.Data.ChannelType.gb , newTask = "New Task" , createNewTask = "Create a new notification task" , taskCreated = "Task created." @@ -50,9 +53,10 @@ gb = de : Texts de = { basics = Messages.Basics.de - , notificationForm = Messages.Comp.NotificationForm.de - , notificationTable = Messages.Comp.NotificationTable.de + , notificationForm = Messages.Comp.DueItemsTaskForm.de + , notificationTable = Messages.Comp.DueItemsTaskList.de , httpError = Messages.Comp.HttpError.de + , channelType = Messages.Data.ChannelType.de , newTask = "Neuer Auftrag" , createNewTask = "Erstelle einen neuen Benachrichtigungsauftrag" , taskCreated = "Auftrag erstellt." diff --git a/modules/webapp/src/main/elm/Messages/Comp/EventSample.elm b/modules/webapp/src/main/elm/Messages/Comp/EventSample.elm new file mode 100644 index 00000000..9af5514d --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/EventSample.elm @@ -0,0 +1,40 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.EventSample exposing + ( Texts + , de + , gb + ) + +import Data.EventType exposing (EventType) +import Http +import Messages.Comp.HttpError +import Messages.Data.EventType + + +type alias Texts = + { eventType : EventType -> Messages.Data.EventType.Texts + , httpError : Http.Error -> String + , selectEvent : String + } + + +gb : Texts +gb = + { eventType = Messages.Data.EventType.gb + , httpError = Messages.Comp.HttpError.gb + , selectEvent = "Select event…" + } + + +de : Texts +de = + { eventType = Messages.Data.EventType.de + , httpError = Messages.Comp.HttpError.de + , selectEvent = "Ereignis wählen…" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm new file mode 100644 index 00000000..329bf483 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm @@ -0,0 +1,37 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.NotificationGotifyForm exposing + ( Texts + , de + , gb + ) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , gotifyUrl : String + , appKey : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , gotifyUrl = "Gotify URL" + , appKey = "App Key" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , gotifyUrl = "Gotify URL" + , appKey = "App Key" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationHookForm.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationHookForm.elm new file mode 100644 index 00000000..e2b30382 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationHookForm.elm @@ -0,0 +1,75 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.NotificationHookForm exposing + ( Texts + , de + , gb + ) + +import Data.EventType exposing (EventType) +import Messages.Basics +import Messages.Comp.ChannelForm +import Messages.Comp.EventSample +import Messages.Data.ChannelType +import Messages.Data.EventType + + +type alias Texts = + { basics : Messages.Basics.Texts + , channelForm : Messages.Comp.ChannelForm.Texts + , eventType : EventType -> Messages.Data.EventType.Texts + , eventSample : Messages.Comp.EventSample.Texts + , channelHeader : Messages.Data.ChannelType.Texts + , enableDisable : String + , eventsInfo : String + , selectEvents : String + , events : String + , samplePayload : String + , toggleAllEvents : String + , eventFilter : String + , eventFilterInfo : String + , eventFilterClickForHelp : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , channelForm = Messages.Comp.ChannelForm.gb + , eventType = Messages.Data.EventType.gb + , eventSample = Messages.Comp.EventSample.gb + , channelHeader = Messages.Data.ChannelType.gb + , enableDisable = "Enabled / Disabled" + , eventsInfo = "Select events that trigger this webhook" + , selectEvents = "Select…" + , events = "Events" + , samplePayload = "Sample Payload" + , toggleAllEvents = "Notify on all events" + , eventFilter = "Event Filter Expression" + , eventFilterInfo = "Optional specify an expression to filter events based on their JSON structure." + , eventFilterClickForHelp = "Click here for help" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , channelForm = Messages.Comp.ChannelForm.de + , eventType = Messages.Data.EventType.de + , eventSample = Messages.Comp.EventSample.de + , channelHeader = Messages.Data.ChannelType.de + , enableDisable = "Aktiviert / Deaktivert" + , eventsInfo = "Wähle die Ereignisse, die diesen webhook auslösen" + , selectEvents = "Wähle…" + , events = "Ereignisse" + , samplePayload = "Beispieldaten" + , toggleAllEvents = "Bei allen Ereignissen" + , eventFilter = "Ereignisfilter" + , eventFilterInfo = "Optionaler Ausdruck zum filtern von Ereignissen auf Basis ihrer JSON Struktur." + , eventFilterClickForHelp = "Klicke für Hilfe" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationHookManage.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationHookManage.elm new file mode 100644 index 00000000..d215ff32 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationHookManage.elm @@ -0,0 +1,106 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.NotificationHookManage exposing + ( Texts + , de + , gb + ) + +import Html exposing (Html, text) +import Http +import Messages.Basics +import Messages.Comp.HttpError +import Messages.Comp.NotificationHookForm +import Messages.Comp.NotificationHookTable +import Messages.Data.ChannelType + + +type alias Texts = + { basics : Messages.Basics.Texts + , notificationForm : Messages.Comp.NotificationHookForm.Texts + , notificationTable : Messages.Comp.NotificationHookTable.Texts + , httpError : Http.Error -> String + , channelType : Messages.Data.ChannelType.Texts + , newHook : String + , matrix : String + , gotify : String + , email : String + , httpRequest : String + , hookCreated : String + , hookUpdated : String + , hookStarted : String + , hookDeleted : String + , deleteThisHook : String + , reallyDeleteHook : String + , formInvalid : String + , invalidJsonFilter : String -> String + , integrate : String + , intoDocspell : String + , postRequestInfo : String + , updateWebhook : String + , addWebhook : String + , notifyEmailInfo : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , notificationForm = Messages.Comp.NotificationHookForm.gb + , notificationTable = Messages.Comp.NotificationHookTable.gb + , httpError = Messages.Comp.HttpError.gb + , channelType = Messages.Data.ChannelType.gb + , newHook = "New Webhook" + , matrix = "Matrix" + , gotify = "Gotify" + , email = "E-Mail" + , httpRequest = "HTTP Request" + , hookCreated = "Webhook created" + , hookUpdated = "Webhook updated" + , hookStarted = "Webhook executed" + , hookDeleted = "Webhook deleted" + , deleteThisHook = "Delete this webhook" + , reallyDeleteHook = "Really delete this webhook?" + , formInvalid = "Please fill in all required fields" + , invalidJsonFilter = \m -> "Event filter invalid: " ++ m + , integrate = "Integrate" + , intoDocspell = "into Docspell" + , postRequestInfo = "Docspell will send POST requests with JSON payload." + , updateWebhook = "Update webhook" + , addWebhook = "Add new webhook" + , notifyEmailInfo = "Get notified via e-mail." + } + + +de : Texts +de = + { basics = Messages.Basics.de + , notificationForm = Messages.Comp.NotificationHookForm.de + , notificationTable = Messages.Comp.NotificationHookTable.de + , httpError = Messages.Comp.HttpError.de + , channelType = Messages.Data.ChannelType.de + , newHook = "Neuer Webhook" + , matrix = "Matrix" + , gotify = "Gotify" + , email = "E-Mail" + , httpRequest = "HTTP Request" + , hookCreated = "Webhook erstellt" + , hookUpdated = "Webhook aktualisiert" + , hookStarted = "Webhook ausgeführt" + , hookDeleted = "Webhook gelöscht" + , deleteThisHook = "Diesen Webhook löschen" + , reallyDeleteHook = "Den webhook wirklich löschen?" + , formInvalid = "Bitte alle erforderlichen Felder ausfüllen" + , invalidJsonFilter = \m -> "Ereignisfilter ist falsch: " ++ m + , integrate = "Integriere" + , intoDocspell = "in Docspell" + , postRequestInfo = "Docspell wird JSON POST requests senden." + , updateWebhook = "Webhook aktualisieren" + , addWebhook = "Neuen Webhook hinzufügen" + , notifyEmailInfo = "Werde per E-Mail benachrichtigt." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationHookTable.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationHookTable.elm new file mode 100644 index 00000000..ddf8c8ff --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationHookTable.elm @@ -0,0 +1,45 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.NotificationHookTable exposing + ( Texts + , de + , gb + ) + +import Data.EventType exposing (EventType) +import Messages.Basics +import Messages.Data.EventType + + +type alias Texts = + { basics : Messages.Basics.Texts + , eventType : EventType -> Messages.Data.EventType.Texts + , enabled : String + , channel : String + , events : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , eventType = Messages.Data.EventType.gb + , enabled = "Enabled" + , channel = "Channel" + , events = "Events" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , eventType = Messages.Data.EventType.de + , enabled = "Aktiv" + , channel = "Kanal" + , events = "Ereignisse" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationHttpForm.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationHttpForm.elm new file mode 100644 index 00000000..e9a2c336 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationHttpForm.elm @@ -0,0 +1,34 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.NotificationHttpForm exposing + ( Texts + , de + , gb + ) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , httpUrl : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , httpUrl = "Http URL" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , httpUrl = "URL" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationMailForm.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationMailForm.elm new file mode 100644 index 00000000..9e88a3c2 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationMailForm.elm @@ -0,0 +1,49 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.NotificationMailForm exposing + ( Texts + , de + , gb + ) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , selectConnection : String + , sendVia : String + , sendViaInfo : String + , recipients : String + , recipientsInfo : String + , recipientsRequired : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , selectConnection = "Select connection..." + , sendVia = "Send via" + , sendViaInfo = "The SMTP connection to use when sending notification mails." + , recipients = "Recipient(s)" + , recipientsInfo = "One or more mail addresses, confirm each by pressing 'Return'." + , recipientsRequired = "At least one recipient is required." + } + + +de : Texts +de = + { basics = Messages.Basics.de + , selectConnection = "Verbindung auswählen…" + , sendVia = "Senden via" + , sendViaInfo = "Die SMTP-Verbindung, die zum Senden der Benachrichtigungs-E-Mails verwendet werden soll." + , recipients = "Empfänger" + , recipientsInfo = "Eine oder mehrere E-Mail-Adressen, jede mit 'Eingabe' bestätigen." + , recipientsRequired = "Mindestens ein Empfänger muss angegeben werden." + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationMatrixForm.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationMatrixForm.elm new file mode 100644 index 00000000..7e44d5c6 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationMatrixForm.elm @@ -0,0 +1,40 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.NotificationMatrixForm exposing + ( Texts + , de + , gb + ) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , homeServer : String + , roomId : String + , accessKey : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , homeServer = "Homeserver URL" + , roomId = "Room ID" + , accessKey = "Access Token" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , homeServer = "Homeserver URL" + , roomId = "Room ID" + , accessKey = "Access Token" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskForm.elm b/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskForm.elm new file mode 100644 index 00000000..96f8cfac --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskForm.elm @@ -0,0 +1,99 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.PeriodicQueryTaskForm exposing + ( Texts + , de + , gb + ) + +import Data.ChannelType exposing (ChannelType) +import Http +import Messages.Basics +import Messages.Comp.CalEventInput +import Messages.Comp.ChannelForm +import Messages.Comp.HttpError +import Messages.Data.ChannelType + + +type alias Texts = + { basics : Messages.Basics.Texts + , calEventInput : Messages.Comp.CalEventInput.Texts + , channelForm : Messages.Comp.ChannelForm.Texts + , httpError : Http.Error -> String + , reallyDeleteTask : String + , startOnce : String + , startTaskNow : String + , deleteThisTask : String + , enableDisable : String + , summary : String + , summaryInfo : String + , schedule : String + , scheduleClickForHelp : String + , scheduleInfo : String + , queryLabel : String + , invalidCalEvent : String + , channelRequired : String + , queryStringRequired : String + , channelHeader : ChannelType -> String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , calEventInput = Messages.Comp.CalEventInput.gb + , channelForm = Messages.Comp.ChannelForm.gb + , httpError = Messages.Comp.HttpError.gb + , reallyDeleteTask = "Really delete this notification task?" + , startOnce = "Start Once" + , startTaskNow = "Start this task now" + , deleteThisTask = "Delete this task" + , enableDisable = "Enable or disable this task." + , summary = "Summary" + , summaryInfo = "Some human readable name, only for displaying" + , schedule = "Schedule" + , scheduleClickForHelp = "Click here for help" + , scheduleInfo = + "Specify how often and when this task should run. " + ++ "Use English 3-letter weekdays. Either a single value, " + ++ "a list (ex. 1,2,3), a range (ex. 1..3) or a '*' (meaning all) " + ++ "is allowed for each part." + , invalidCalEvent = "The calendar event is not valid." + , queryLabel = "Query" + , channelRequired = "A valid channel must be given." + , queryStringRequired = "A query string must be supplied" + , channelHeader = \ct -> "Connection details for " ++ Messages.Data.ChannelType.gb ct + } + + +de : Texts +de = + { basics = Messages.Basics.de + , calEventInput = Messages.Comp.CalEventInput.de + , channelForm = Messages.Comp.ChannelForm.de + , httpError = Messages.Comp.HttpError.de + , reallyDeleteTask = "Diesen Benachrichtigungsauftrag wirklich löschen?" + , startOnce = "Jetzt starten" + , startTaskNow = "Starte den Auftrag sofort" + , deleteThisTask = "Den Auftrag löschen" + , enableDisable = "Auftrag aktivieren oder deaktivieren" + , summary = "Kurzbeschreibung" + , summaryInfo = "Eine kurze lesbare Zusammenfassung, nur für die Anzeige" + , schedule = "Zeitplan" + , scheduleClickForHelp = "Klicke für Hilfe" + , scheduleInfo = + "Gib an, wie oft und wann der Auftrag laufen soll. " + ++ "Verwende englische 3-Buchstaben Wochentage. Entweder ein einzelner Wert, " + ++ "eine Liste (wie `1,2,3`), eine Bereich (wie `1..3`) oder ein '*' (für alle) " + ++ "ist mögich für jeden Teil." + , invalidCalEvent = "Das Kalenderereignis ist nicht gültig." + , queryLabel = "Abfrage" + , channelRequired = "Ein Versandkanal muss angegeben werden." + , queryStringRequired = "Eine Suchabfrage muss angegeben werden." + , channelHeader = \ct -> "Details für " ++ Messages.Data.ChannelType.de ct + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskList.elm b/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskList.elm new file mode 100644 index 00000000..0920b6f5 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskList.elm @@ -0,0 +1,43 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.PeriodicQueryTaskList exposing + ( Texts + , de + , gb + ) + +import Messages.Basics + + +type alias Texts = + { basics : Messages.Basics.Texts + , summary : String + , schedule : String + , connection : String + , recipients : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , summary = "Summary" + , schedule = "Schedule" + , connection = "Connection" + , recipients = "Recipients" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , summary = "Kurzbeschreibung" + , schedule = "Zeitplan" + , connection = "Verbindung" + , recipients = "Empfänger" + } diff --git a/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskManage.elm b/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskManage.elm new file mode 100644 index 00000000..f811f2f8 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Comp/PeriodicQueryTaskManage.elm @@ -0,0 +1,78 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Comp.PeriodicQueryTaskManage exposing + ( Texts + , de + , gb + ) + +import Http +import Messages.Basics +import Messages.Comp.HttpError +import Messages.Comp.PeriodicQueryTaskForm +import Messages.Comp.PeriodicQueryTaskList +import Messages.Data.ChannelType + + +type alias Texts = + { basics : Messages.Basics.Texts + , notificationForm : Messages.Comp.PeriodicQueryTaskForm.Texts + , notificationTable : Messages.Comp.PeriodicQueryTaskList.Texts + , httpError : Http.Error -> String + , channelType : Messages.Data.ChannelType.Texts + , newTask : String + , createNewTask : String + , taskCreated : String + , taskUpdated : String + , taskStarted : String + , taskDeleted : String + , matrix : String + , gotify : String + , email : String + , httpRequest : String + } + + +gb : Texts +gb = + { basics = Messages.Basics.gb + , notificationForm = Messages.Comp.PeriodicQueryTaskForm.gb + , notificationTable = Messages.Comp.PeriodicQueryTaskList.gb + , httpError = Messages.Comp.HttpError.gb + , channelType = Messages.Data.ChannelType.gb + , newTask = "New Task" + , createNewTask = "Create a new notification task" + , taskCreated = "Task created." + , taskUpdated = "Task updated." + , taskStarted = "Task started." + , taskDeleted = "Task deleted." + , matrix = "Matrix" + , gotify = "Gotify" + , email = "E-Mail" + , httpRequest = "HTTP Request" + } + + +de : Texts +de = + { basics = Messages.Basics.de + , notificationForm = Messages.Comp.PeriodicQueryTaskForm.de + , notificationTable = Messages.Comp.PeriodicQueryTaskList.de + , httpError = Messages.Comp.HttpError.de + , channelType = Messages.Data.ChannelType.de + , newTask = "Neuer Auftrag" + , createNewTask = "Erstelle einen neuen Benachrichtigungsauftrag" + , taskCreated = "Auftrag erstellt." + , taskUpdated = "Auftrag aktualisiert." + , taskStarted = "Auftrag gestartet." + , taskDeleted = "Auftrag gelöscht." + , matrix = "Matrix" + , gotify = "Gotify" + , email = "E-Mail" + , httpRequest = "HTTP Request" + } diff --git a/modules/webapp/src/main/elm/Messages/Data/ChannelType.elm b/modules/webapp/src/main/elm/Messages/Data/ChannelType.elm new file mode 100644 index 00000000..4522fa27 --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/ChannelType.elm @@ -0,0 +1,46 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Data.ChannelType exposing (Texts, de, gb) + +import Data.ChannelType exposing (ChannelType) + + +type alias Texts = + ChannelType -> String + + +gb : Texts +gb ct = + case ct of + Data.ChannelType.Matrix -> + "Matrix" + + Data.ChannelType.Gotify -> + "Gotify" + + Data.ChannelType.Mail -> + "E-Mail" + + Data.ChannelType.Http -> + "HTTP request" + + +de : Texts +de ct = + case ct of + Data.ChannelType.Matrix -> + "Matrix" + + Data.ChannelType.Gotify -> + "Gotify" + + Data.ChannelType.Mail -> + "E-Mail" + + Data.ChannelType.Http -> + "HTTP Request" diff --git a/modules/webapp/src/main/elm/Messages/Data/EventType.elm b/modules/webapp/src/main/elm/Messages/Data/EventType.elm new file mode 100644 index 00000000..99ccb99e --- /dev/null +++ b/modules/webapp/src/main/elm/Messages/Data/EventType.elm @@ -0,0 +1,78 @@ +{- + Copyright 2020 Eike K. & Contributors + + SPDX-License-Identifier: AGPL-3.0-or-later +-} + + +module Messages.Data.EventType exposing + ( Texts + , de + , gb + ) + +import Data.EventType exposing (EventType(..)) + + +type alias Texts = + { name : String + , info : String + } + + +gb : EventType -> Texts +gb et = + case et of + TagsChanged -> + { name = "Tags changed" + , info = "Whenever a tag on an item is added or removed" + } + + SetFieldValue -> + { name = "Set field value" + , info = "Whenever a custom field is set to a value" + } + + DeleteFieldValue -> + { name = "Delete field value" + , info = "Whenever a custom field is removed" + } + + JobSubmitted -> + { name = "Job submitted" + , info = "Whenever a new job is submitted" + } + + JobDone -> + { name = "Job done" + , info = "Whenever a new job finished" + } + + +de : EventType -> Texts +de et = + case et of + TagsChanged -> + { name = "Tags geändert" + , info = "Wenn ein tag hinzugefügt oder entfernt wird" + } + + SetFieldValue -> + { name = "Benutzerfeldwert ändert" + , info = "Wenn für ein Benutzerfeld ein Wert gesetzt wird" + } + + DeleteFieldValue -> + { name = "Benutzerfeldwert entfernt" + , info = "Wenn der Wert für ein Benuzterfeld entfernt wird" + } + + JobSubmitted -> + { name = "Auftrag gestartet" + , info = "Wenn ein neuer Auftrag gestartet wird" + } + + JobDone -> + { name = "Auftrag beendet" + , info = "Wenn ein Auftrag beendet wurde" + } diff --git a/modules/webapp/src/main/elm/Messages/Page/UserSettings.elm b/modules/webapp/src/main/elm/Messages/Page/UserSettings.elm index 33531d08..a1bb4e39 100644 --- a/modules/webapp/src/main/elm/Messages/Page/UserSettings.elm +++ b/modules/webapp/src/main/elm/Messages/Page/UserSettings.elm @@ -12,10 +12,12 @@ module Messages.Page.UserSettings exposing ) import Messages.Comp.ChangePasswordForm +import Messages.Comp.DueItemsTaskManage import Messages.Comp.EmailSettingsManage import Messages.Comp.ImapSettingsManage -import Messages.Comp.NotificationManage +import Messages.Comp.NotificationHookManage import Messages.Comp.OtpSetup +import Messages.Comp.PeriodicQueryTaskManage import Messages.Comp.ScanMailboxManage import Messages.Comp.UiSettingsManage @@ -25,8 +27,10 @@ type alias Texts = , uiSettingsManage : Messages.Comp.UiSettingsManage.Texts , emailSettingsManage : Messages.Comp.EmailSettingsManage.Texts , imapSettingsManage : Messages.Comp.ImapSettingsManage.Texts - , notificationManage : Messages.Comp.NotificationManage.Texts + , notificationManage : Messages.Comp.DueItemsTaskManage.Texts , scanMailboxManage : Messages.Comp.ScanMailboxManage.Texts + , notificationHookManage : Messages.Comp.NotificationHookManage.Texts + , periodicQueryTask : Messages.Comp.PeriodicQueryTaskManage.Texts , otpSetup : Messages.Comp.OtpSetup.Texts , userSettings : String , uiSettings : String @@ -36,11 +40,16 @@ type alias Texts = , emailSettingImap : String , changePassword : String , uiSettingsInfo : String - , notificationInfoText : String - , notificationRemindDaysInfo : String , scanMailboxInfo1 : String , scanMailboxInfo2 : String , otpMenu : String + , webhooks : String + , genericQueries : String + , dueItems : String + , notificationInfoText : String + , webhookInfoText : String + , dueItemsInfoText : String + , periodicQueryInfoText : String } @@ -50,8 +59,10 @@ gb = , uiSettingsManage = Messages.Comp.UiSettingsManage.gb , emailSettingsManage = Messages.Comp.EmailSettingsManage.gb , imapSettingsManage = Messages.Comp.ImapSettingsManage.gb - , notificationManage = Messages.Comp.NotificationManage.gb + , notificationManage = Messages.Comp.DueItemsTaskManage.gb , scanMailboxManage = Messages.Comp.ScanMailboxManage.gb + , notificationHookManage = Messages.Comp.NotificationHookManage.gb + , periodicQueryTask = Messages.Comp.PeriodicQueryTaskManage.gb , otpSetup = Messages.Comp.OtpSetup.gb , userSettings = "User Settings" , uiSettings = "UI Settings" @@ -63,13 +74,6 @@ gb = , uiSettingsInfo = "These settings only affect the web ui. They are stored in the browser, " ++ "so they are separated between browsers and devices." - , notificationInfoText = - """ - Docspell can notify you once the due dates of your items - come closer. Notification is done via e-mail. You need to - provide a connection in your e-mail settings.""" - , notificationRemindDaysInfo = - "Docspell finds all items that are due in *Remind Days* days and sends this list via e-mail." , scanMailboxInfo1 = "Docspell can scan folders of your mailbox to import your mails. " ++ "You need to provide a connection in " @@ -85,6 +89,28 @@ gb = adjust the schedule to avoid reading over the same mails again.""" , otpMenu = "Two Factor Authentication" + , webhooks = "Webhooks" + , genericQueries = "Generic Queries" + , dueItems = "Due Items Query" + , notificationInfoText = """ + +Docspell can send notification messages on various events. You can +choose from these channels to send messages: +[Matrix](https://matrix.org), [Gotify](https://gotify.net) or E-Mail. +At last you can send a plain http request with the event details in +its payload. + +Additionally, you can setup queries that are executed periodically. +The results are send as a notification message. + +When creating a new notification task, choose first the communication +channel. + +""" + , webhookInfoText = """Webhooks execute http request upon certain events in docspell. +""" + , dueItemsInfoText = """Docspell can notify you once the due dates of your items come closer. """ + , periodicQueryInfoText = "You can define a custom query that gets executed periodically." } @@ -94,8 +120,10 @@ de = , uiSettingsManage = Messages.Comp.UiSettingsManage.de , emailSettingsManage = Messages.Comp.EmailSettingsManage.de , imapSettingsManage = Messages.Comp.ImapSettingsManage.de - , notificationManage = Messages.Comp.NotificationManage.de + , notificationManage = Messages.Comp.DueItemsTaskManage.de , scanMailboxManage = Messages.Comp.ScanMailboxManage.de + , notificationHookManage = Messages.Comp.NotificationHookManage.de + , periodicQueryTask = Messages.Comp.PeriodicQueryTaskManage.de , otpSetup = Messages.Comp.OtpSetup.de , userSettings = "Benutzereinstellung" , uiSettings = "Oberfläche" @@ -106,13 +134,6 @@ de = , changePassword = "Passwort ändern" , uiSettingsInfo = "Diese Einstellungen sind für die Web-Oberfläche." - , notificationInfoText = - """ - Docspell kann eine E-Mail versenden, sobald das - Fälligkeitsdatum von Dokumenten näher kommt. Dafür muss eine - E-Mail-SMTP-Verbindung konfiguriert werden..""" - , notificationRemindDaysInfo = - "Docspell sucht Dokumente die in X Tagen fällig sind und sendet diese Liste als E-Mail." , scanMailboxInfo1 = """Docspell kann Postfächer durchsuchen und E-Mails importieren. Dafür sind E-Mail-Einstellungen (IMAP) notwendig.""" @@ -129,4 +150,26 @@ E-Mail-Einstellungen (IMAP) notwendig.""" gleichen E-Mails möglichst nicht noch einmal eingelesen werden.""" , otpMenu = "Zwei-Faktor-Authentifizierung" + , webhooks = "Webhooks" + , genericQueries = "Periodische Abfragen" + , dueItems = "Fällige Dokumente" + , notificationInfoText = """ + +Docspell kann Benachrichtigungen bei gewissen Ereignissen versenden. +Es kann aus diesen Versandkanälen gewählt werden: +[Matrix](https://matrix.org), [Gotify](https://gotify.net) oder +E-Mail. Zusätzlich kann das HTTP request direkt empfangen werden, was +alle Details zu einem Ereignis enthält. + + +Ausserdem können periodische Suchabfragen erstellt werden, dessen +Ergebnis dann als Benachrichtigung versendet wird. + +Beim Erstellen eines neuen Auftrags muss zunächst der gewünschte +Versandkanal gewählt werden. + +""" + , webhookInfoText = """Webhooks versenden HTTP Requests wenn bestimmte Ereignisse in Docspell auftreten.""" + , dueItemsInfoText = """Docspell kann dich benachrichtigen, sobald das Fälligkeitsdatum von Dokumenten näher kommt. """ + , periodicQueryInfoText = "Hier können beliebige Abfragen definiert werden, welche regelmäßig ausgeführt werden." } diff --git a/modules/webapp/src/main/elm/Page/UserSettings/Data.elm b/modules/webapp/src/main/elm/Page/UserSettings/Data.elm index 5352d3ac..58b761e0 100644 --- a/modules/webapp/src/main/elm/Page/UserSettings/Data.elm +++ b/modules/webapp/src/main/elm/Page/UserSettings/Data.elm @@ -13,10 +13,12 @@ module Page.UserSettings.Data exposing ) import Comp.ChangePasswordForm +import Comp.DueItemsTaskManage import Comp.EmailSettingsManage import Comp.ImapSettingsManage -import Comp.NotificationManage +import Comp.NotificationHookManage import Comp.OtpSetup +import Comp.PeriodicQueryTaskManage import Comp.ScanMailboxManage import Comp.UiSettingsManage import Data.Flags exposing (Flags) @@ -28,10 +30,12 @@ type alias Model = , changePassModel : Comp.ChangePasswordForm.Model , emailSettingsModel : Comp.EmailSettingsManage.Model , imapSettingsModel : Comp.ImapSettingsManage.Model - , notificationModel : Comp.NotificationManage.Model + , notificationModel : Comp.DueItemsTaskManage.Model , scanMailboxModel : Comp.ScanMailboxManage.Model , uiSettingsModel : Comp.UiSettingsManage.Model , otpSetupModel : Comp.OtpSetup.Model + , notificationHookModel : Comp.NotificationHookManage.Model + , periodicQueryModel : Comp.PeriodicQueryTaskManage.Model } @@ -43,19 +47,29 @@ init flags settings = ( otpm, otpc ) = Comp.OtpSetup.init flags + + ( nhm, nhc ) = + Comp.NotificationHookManage.init flags + + ( pqm, pqc ) = + Comp.PeriodicQueryTaskManage.init flags in ( { currentTab = Just UiSettingsTab , changePassModel = Comp.ChangePasswordForm.emptyModel , emailSettingsModel = Comp.EmailSettingsManage.emptyModel , imapSettingsModel = Comp.ImapSettingsManage.emptyModel - , notificationModel = Tuple.first (Comp.NotificationManage.init flags) + , notificationModel = Tuple.first (Comp.DueItemsTaskManage.init flags) , scanMailboxModel = Tuple.first (Comp.ScanMailboxManage.init flags) , uiSettingsModel = um , otpSetupModel = otpm + , notificationHookModel = nhm + , periodicQueryModel = pqm } , Cmd.batch [ Cmd.map UiSettingsMsg uc , Cmd.map OtpSetupMsg otpc + , Cmd.map NotificationHookMsg nhc + , Cmd.map PeriodicQueryMsg pqc ] ) @@ -65,6 +79,9 @@ type Tab | EmailSettingsTab | ImapSettingsTab | NotificationTab + | NotificationWebhookTab + | NotificationQueriesTab + | NotificationDueItemsTab | ScanMailboxTab | UiSettingsTab | OtpTab @@ -74,10 +91,12 @@ type Msg = SetTab Tab | ChangePassMsg Comp.ChangePasswordForm.Msg | EmailSettingsMsg Comp.EmailSettingsManage.Msg - | NotificationMsg Comp.NotificationManage.Msg + | NotificationMsg Comp.DueItemsTaskManage.Msg | ImapSettingsMsg Comp.ImapSettingsManage.Msg | ScanMailboxMsg Comp.ScanMailboxManage.Msg | UiSettingsMsg Comp.UiSettingsManage.Msg | OtpSetupMsg Comp.OtpSetup.Msg + | NotificationHookMsg Comp.NotificationHookManage.Msg + | PeriodicQueryMsg Comp.PeriodicQueryTaskManage.Msg | UpdateSettings | ReceiveBrowserSettings StoredUiSettings diff --git a/modules/webapp/src/main/elm/Page/UserSettings/Update.elm b/modules/webapp/src/main/elm/Page/UserSettings/Update.elm index ca321d5a..263288a2 100644 --- a/modules/webapp/src/main/elm/Page/UserSettings/Update.elm +++ b/modules/webapp/src/main/elm/Page/UserSettings/Update.elm @@ -8,10 +8,12 @@ module Page.UserSettings.Update exposing (UpdateResult, update) import Comp.ChangePasswordForm +import Comp.DueItemsTaskManage import Comp.EmailSettingsManage import Comp.ImapSettingsManage -import Comp.NotificationManage +import Comp.NotificationHookManage import Comp.OtpSetup +import Comp.PeriodicQueryTaskManage import Comp.ScanMailboxManage import Comp.UiSettingsManage import Data.Flags exposing (Flags) @@ -62,10 +64,32 @@ update flags settings msg model = UpdateResult m Cmd.none Sub.none Nothing NotificationTab -> + { model = m + , cmd = Cmd.none + , sub = Sub.none + , newSettings = Nothing + } + + NotificationWebhookTab -> + { model = m + , cmd = Cmd.none + , sub = Sub.none + , newSettings = Nothing + } + + NotificationQueriesTab -> let initCmd = Cmd.map NotificationMsg - (Tuple.second (Comp.NotificationManage.init flags)) + (Tuple.second (Comp.DueItemsTaskManage.init flags)) + in + UpdateResult m initCmd Sub.none Nothing + + NotificationDueItemsTab -> + let + initCmd = + Cmd.map NotificationMsg + (Tuple.second (Comp.DueItemsTaskManage.init flags)) in UpdateResult m initCmd Sub.none Nothing @@ -119,7 +143,7 @@ update flags settings msg model = NotificationMsg lm -> let ( m2, c2 ) = - Comp.NotificationManage.update flags lm model.notificationModel + Comp.DueItemsTaskManage.update flags lm model.notificationModel in { model = { model | notificationModel = m2 } , cmd = Cmd.map NotificationMsg c2 @@ -160,6 +184,17 @@ update flags settings msg model = , newSettings = Nothing } + NotificationHookMsg lm -> + let + ( hm, hc ) = + Comp.NotificationHookManage.update flags lm model.notificationHookModel + in + { model = { model | notificationHookModel = hm } + , cmd = Cmd.map NotificationHookMsg hc + , sub = Sub.none + , newSettings = Nothing + } + UpdateSettings -> update flags settings @@ -172,3 +207,14 @@ update flags settings msg model = Comp.UiSettingsManage.ReceiveBrowserSettings sett in update flags settings (UiSettingsMsg lm) model + + PeriodicQueryMsg lm -> + let + ( pqm, pqc, pqs ) = + Comp.PeriodicQueryTaskManage.update flags lm model.periodicQueryModel + in + { model = { model | periodicQueryModel = pqm } + , cmd = Cmd.map PeriodicQueryMsg pqc + , sub = Sub.map PeriodicQueryMsg pqs + , newSettings = Nothing + } diff --git a/modules/webapp/src/main/elm/Page/UserSettings/View2.elm b/modules/webapp/src/main/elm/Page/UserSettings/View2.elm index fbbef682..b466f038 100644 --- a/modules/webapp/src/main/elm/Page/UserSettings/View2.elm +++ b/modules/webapp/src/main/elm/Page/UserSettings/View2.elm @@ -8,10 +8,12 @@ module Page.UserSettings.View2 exposing (viewContent, viewSidebar) import Comp.ChangePasswordForm +import Comp.DueItemsTaskManage import Comp.EmailSettingsManage import Comp.ImapSettingsManage -import Comp.NotificationManage +import Comp.NotificationHookManage import Comp.OtpSetup +import Comp.PeriodicQueryTaskManage import Comp.ScanMailboxManage import Comp.UiSettingsManage import Data.Flags exposing (Flags) @@ -27,6 +29,24 @@ import Styles as S viewSidebar : Texts -> Bool -> Flags -> UiSettings -> Model -> Html Msg viewSidebar texts visible _ _ model = + let + isNotificationTab = + case model.currentTab of + Just NotificationTab -> + True + + Just NotificationQueriesTab -> + True + + Just NotificationWebhookTab -> + True + + Just NotificationDueItemsTab -> + True + + _ -> + False + in div [ id "sidebar" , class S.sidebar @@ -50,16 +70,56 @@ viewSidebar texts visible _ _ model = [ class "ml-3" ] [ text texts.uiSettings ] ] - , a - [ href "#" - , onClick (SetTab NotificationTab) - , menuEntryActive model NotificationTab - , class S.sidebarLink - ] - [ i [ class "fa fa-bullhorn" ] [] - , span - [ class "ml-3" ] - [ text texts.notifications ] + , div [] + [ a + [ href "#" + , onClick (SetTab NotificationTab) + , menuEntryActive model NotificationTab + , class S.sidebarLink + ] + [ i [ class "fa fa-bullhorn" ] [] + , span + [ class "ml-3" ] + [ text texts.notifications ] + ] + , div + [ class "ml-5 flex flex-col" + , classList [ ( "hidden", not isNotificationTab ) ] + ] + [ a + [ href "#" + , onClick (SetTab NotificationWebhookTab) + , menuEntryActive model NotificationWebhookTab + , class S.sidebarLink + ] + [ i [ class "fa fa-bell" ] [] + , span + [ class "ml-3" ] + [ text texts.webhooks ] + ] + , a + [ href "#" + , onClick (SetTab NotificationDueItemsTab) + , menuEntryActive model NotificationDueItemsTab + , class S.sidebarLink + ] + [ i [ class "fa fa-history" ] [] + , span + [ class "ml-3" ] + [ text texts.dueItems ] + ] + , a + [ href "#" + , onClick (SetTab NotificationQueriesTab) + , menuEntryActive model NotificationQueriesTab + , class S.sidebarLink + ] + [ i [ class "fa fa-history" ] [] + , span + [ class "ml-3" ] + [ text texts.genericQueries ] + ] + ] ] , a [ href "#" @@ -134,7 +194,16 @@ viewContent texts flags settings model = viewEmailSettings texts settings model Just NotificationTab -> - viewNotificationManage texts settings model + viewNotificationInfo texts settings model + + Just NotificationWebhookTab -> + viewNotificationHooks texts settings model + + Just NotificationQueriesTab -> + viewNotificationQueries texts settings model + + Just NotificationDueItemsTab -> + viewNotificationDueItems texts settings model Just ImapSettingsTab -> viewImapSettings texts settings model @@ -268,8 +337,8 @@ viewImapSettings texts settings model = ] -viewNotificationManage : Texts -> UiSettings -> Model -> List (Html Msg) -viewNotificationManage texts settings model = +viewNotificationInfo : Texts -> UiSettings -> Model -> List (Html Msg) +viewNotificationInfo texts settings model = [ h2 [ class S.header1 , class "inline-flex items-center" @@ -279,20 +348,119 @@ viewNotificationManage texts settings model = [ text texts.notifications ] ] - , p [ class "opacity-80 text-lg mb-3" ] - [ text texts.notificationInfoText + , Markdown.toHtml [ class "opacity-80 text-lg max-w-prose mb-3 markdown-preview" ] texts.notificationInfoText + , div [ class "mt-2" ] + [ ul [ class "list-none ml-8" ] + [ li [ class "py-2" ] + [ a + [ href "#" + , onClick (SetTab NotificationWebhookTab) + , class S.link + ] + [ i [ class "fa fa-bell" ] [] + , span + [ class "ml-3" ] + [ text texts.webhooks ] + ] + , div [ class "ml-3 text-sm opacity-50" ] + [ text texts.webhookInfoText + ] + ] + , li [ class "py-2" ] + [ a + [ href "#" + , onClick (SetTab NotificationDueItemsTab) + , class S.link + ] + [ i [ class "fa fa-history" ] [] + , span + [ class "ml-3" ] + [ text texts.dueItems ] + ] + , div [ class "ml-3 text-sm opacity-50" ] + [ text texts.dueItemsInfoText + ] + ] + , li [ class "py-2" ] + [ a + [ href "#" + , onClick (SetTab NotificationQueriesTab) + , class S.link + ] + [ i [ class "fa fa-history" ] [] + , span + [ class "ml-3" ] + [ text texts.genericQueries ] + ] + , div [ class "ml-3 text-sm opacity-50" ] + [ text texts.periodicQueryInfoText + ] + ] + ] ] - , p [ class "opacity-80 text-lg mb-3" ] - [ Markdown.toHtml [] texts.notificationRemindDaysInfo + ] + + +viewNotificationDueItems : Texts -> UiSettings -> Model -> List (Html Msg) +viewNotificationDueItems texts settings model = + [ h2 + [ class S.header1 + , class "inline-flex items-center" ] + [ i [ class "fa fa-history" ] [] + , div [ class "ml-3" ] + [ text texts.dueItems + ] + ] + , Markdown.toHtml [ class "opacity-80 text-lg mb-3 markdown-preview" ] texts.dueItemsInfoText , Html.map NotificationMsg - (Comp.NotificationManage.view2 texts.notificationManage + (Comp.DueItemsTaskManage.view2 texts.notificationManage settings model.notificationModel ) ] +viewNotificationQueries : Texts -> UiSettings -> Model -> List (Html Msg) +viewNotificationQueries texts settings model = + [ h2 + [ class S.header1 + , class "inline-flex items-center" + ] + [ i [ class "fa fa-history" ] [] + , div [ class "ml-3" ] + [ text texts.genericQueries + ] + ] + , Markdown.toHtml [ class "opacity-80 text-lg mb-3 markdown-preview" ] texts.periodicQueryInfoText + , Html.map PeriodicQueryMsg + (Comp.PeriodicQueryTaskManage.view texts.periodicQueryTask + settings + model.periodicQueryModel + ) + ] + + +viewNotificationHooks : Texts -> UiSettings -> Model -> List (Html Msg) +viewNotificationHooks texts settings model = + [ h2 + [ class S.header1 + , class "inline-flex items-center" + ] + [ i [ class "fa fa-bell" ] [] + , div [ class "ml-3" ] + [ text texts.webhooks + ] + ] + , Markdown.toHtml [ class "opacity-80 text-lg mb-3 markdown-preview" ] texts.webhookInfoText + , Html.map NotificationHookMsg + (Comp.NotificationHookManage.view texts.notificationHookManage + settings + model.notificationHookModel + ) + ] + + viewScanMailboxManage : Texts -> Flags -> UiSettings -> Model -> List (Html Msg) viewScanMailboxManage texts flags settings model = [ h2 diff --git a/modules/webapp/src/main/elm/Styles.elm b/modules/webapp/src/main/elm/Styles.elm index e7cbdb6e..2942ccbe 100644 --- a/modules/webapp/src/main/elm/Styles.elm +++ b/modules/webapp/src/main/elm/Styles.elm @@ -7,6 +7,8 @@ module Styles exposing (..) +import Svg exposing (Svg) + sidebar : String sidebar = @@ -348,6 +350,11 @@ header3 = " text-xl mb-3 font-medium tracking-wide " +formHeader : String +formHeader = + header3 ++ " text-xl mb-4 font-medium tracking-wide border-b dark:border-bluegray-300 border-gray-800" + + editLinkTableCellStyle : String editLinkTableCellStyle = "w-px whitespace-nowrap pr-2 md:pr-4 py-4 md:py-2" diff --git a/project/Dependencies.scala b/project/Dependencies.scala index f91c965a..75291f3c 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -231,10 +231,19 @@ object Dependencies { "org.http4s" %% "http4s-blaze-server" % Http4sVersion ) - val circe = Seq( - "io.circe" %% "circe-generic" % CirceVersion, + val circeCore = Seq( + "io.circe" %% "circe-core" % CirceVersion + ) + val circeParser = Seq( "io.circe" %% "circe-parser" % CirceVersion ) + val circe = + circeCore ++ circeParser ++ Seq( + "io.circe" %% "circe-generic" % CirceVersion + ) + val circeGenericExtra = Seq( + "io.circe" %% "circe-generic-extras" % CirceVersion + ) // https://github.com/Log4s/log4s;ASL 2.0 val loggingApi = Seq( @@ -285,6 +294,9 @@ object Dependencies { val yamusca = Seq( "com.github.eikek" %% "yamusca-core" % YamuscaVersion ) + val yamuscaCirce = Seq( + "com.github.eikek" %% "yamusca-circe" % YamuscaVersion + ) val munit = Seq( "org.scalameta" %% "munit" % MUnitVersion, diff --git a/website/site/content/docs/features/_index.md b/website/site/content/docs/features/_index.md index 6f13e940..23fa40d9 100644 --- a/website/site/content/docs/features/_index.md +++ b/website/site/content/docs/features/_index.md @@ -47,8 +47,9 @@ description = "A list of features and limitations." - [Share](@/docs/webapp/share.md) documents via cryptic public links (optionally protected by a password) - [Send documents via e-mail](@/docs/webapp/mailitem.md) -- [E-Mail notification](@/docs/webapp/notifydueitems.md) for documents - with due dates +- [Notifications](@/docs/webapp/notification.md) for documents with + due dates or events via E-Mail, [Matrix](https://matrix.org) or + [Gotify](https://gotify.net) - [Read your mailboxes](@/docs/webapp/scanmailbox.md) via IMAP to import mails into docspell - [Edit multiple items](@/docs/webapp/multiedit.md) at once diff --git a/website/site/content/docs/jsonminiquery/_index.md b/website/site/content/docs/jsonminiquery/_index.md new file mode 100644 index 00000000..b48b0db4 --- /dev/null +++ b/website/site/content/docs/jsonminiquery/_index.md @@ -0,0 +1,258 @@ ++++ +title = "JSON (mini) query" +[extra] +mktoc = true +hidden = true ++++ + +A "JSON mini query" is a simple expression that evaluates to `true` or +`false` for any given JSON value. + +It is used in docspell to filter notification events. + +The examples shown here assume the JSON at [the end of this +page](#sample-json). + +# Structure + +A json mini query is a sequence of "segments" where each one selects +contents from the "current result". The current result is always a +list of JSON values and starts out with a single element list +containing the given root JSON document. + +When the expression is applied, it is read from left to right where +each segment is evaluated against the JSON. All results are always +aggregated into a single list which is handed to the next segment as +input. Each segment of the expression is always applied to every +element in the list. + +The expression evaluates to `true` if the final result is non-empty +and to `false` otherwise. So the actual values selected at the and are +not really of interest. It only matters if the last result is the +empty list or not. + +There are the following possible segments: + +- selecting fields: `fieldname[,fieldname2,…]` +- selecting specific array elements: `(0[,1,…])` +- filter list of nodes against given values: `=some-value`, + `!some-value` +- combining the above (sequence, `&` and `|`) + + +## Field selection + +The simplest segment is just a field name. It looks up the field name +in the current JSON result and replaces each element in the result +with the value at that field. + +``` +query: a +current result: [{"a":1,"b":2}, {"a":5, "b":2}] +next result: [1, 5] +``` + +You can select multiple fields at once by separating names by comma. +This simply combines all results into a list: + +``` +query: a,b +current result: [{"a":1,"b":2}, {"a":5, "b":2}] +next result: [1, 2, 5, 2] +``` + +You can use dot-notation combining several field selection segments to +select elements deeper in the JSON: + +``` +query: a.b.x,y +current result: + [{"a": {"b": {"x": 1, "y": 2}}, "v": 0}, + {"a": {"b": {"y": 9, "b": 2}}, "z": 0}] +next result: [1, 2, 9] +``` + + +## Array selection + +When looking at an array, you can select specific elements by their +indexes. To distinguish it from field selection, you must surround it +by parens: + +``` +query: (0,2) +current result: [[1,2,3,4]] +next result: [1,3] +``` + +If you combine field selection and array selection, keep in mind that +a previous field selection combines both arrays into one before array +selection is used! + +``` +query: a(0,2) +current result: [{"a": [10,9,8,7]}, {"a": [1,2,3,4]}] +next result: [10,8] +``` + + +## Matching Values + +You can filter elements of the current result based on their value. +This only works for primitive elements. + +- equals (case insensitive): `=` +- not equals (case insensitive): `!` + +Values can be given either as a simple string or, should it contain +whitespace or brackets/parens, you need to enclose it either in single +or double quotes. If you want to check for `null` use the special +`*null*` value. + +The match will be applied to all elements in the current result and +filters out those that don't match. + +``` +query: =blue +current result: ["blue", "green", "red"] +next result: ["blue"] +``` + +``` +query: color=blue +current result: + [{"color": "blue", "count": 2}, + {"color": "blue", "count": 1}, + {"color": "red", "count": 3}] +next result:["blue", "blue"] +``` + +## Combining + +The above expressions can be combined by writing one after the other, +sequencing them. This has been shown in some examples above. The next +segment will be applied to the result of the previous segment. When +sequencing field names they must be separated by a dot. + +Another form is to combine several expressions using `&` or `|`. The +results of all sub expressions will be concatenated into a single +list. When using `&`, results are only concatenated if all lists are +not empty; otherwise the result is the empty list. + +This example filters all `count` equal to `6` and all `name` equal to +`max`. Since there are now `count`s with value `6`, the final result +is empty. + +``` +query: [count=6 & name=max] +current result: + [{"name":"max", "count":4}, + {"name":"me", "count": 3}, + {"name":"max", "count": 3} + ] +next result: [] +``` + +Using `|` for combining lets all the `max` values through: + +``` +query: [count=6 & name=max] +current result: + [{"name":"max", "count":4}, + {"name":"me", "count": 3}, + {"name":"max", "count": 3} + ] +next result: ["max", "max"] +``` + +## Example walkthrough + +Let's look at an example: + +``` +content.added,removed[name=Invoice | category=expense] +``` + +Starting out with the root JSON document, a list is created containing +it as the only element: + +``` +( {"eventType": "TagsChanged", "content: {…}, …} ) +``` + +Then the field `content` is selected. This changes the list to contain +this sub-document: + +``` +( {"account": "demo", "added":[…], "removed":[…], …} ) +``` + +Then two fields are selected. They both select arrays. Both results +are combined into a single list and arrays are flattened. So the +result after `content.added,removed` looks like this: + +``` +( {"id":"Fy4…",name="…",category="…"}, {"id":"7zae…",…}, {"id":"GbXg…",…} ) +``` + +At last, the remaining elements are filtered. It resolve all `name` +fields and keeps only `invoice` values. It also resolves `category` +and keeps only `expense` values. Both lists are then concatenated into +one. The final result is then `["Invoice", "expense"]`, which matches +the sample json data below. + + +# Sample JSON + +Some examples assume the following JSON: + +```json +{ + "eventType": "TagsChanged", + "account": { + "collective": "demo", + "user": "demo", + "login": "demo" + }, + "content": { + "account": "demo", + "items": [ + { + "id": "4PvMM4m7Fwj-FsPRGxYt9zZ-uUzi35S2rEX-usyDEVyheR8", + "name": "MapleSirupLtd_202331.pdf", + "dateMillis": 1633557740733, + "date": "2021-10-06", + "direction": "incoming", + "state": "confirmed", + "dueDateMillis": 1639173740733, + "dueDate": "2021-12-10", + "source": "webapp", + "overDue": false, + "dueIn": "in 3 days", + "corrOrg": "Acme AG", + "notes": null + } + ], + "added": [ + { + "id": "Fy4VC6hQwcL-oynrHaJg47D-Q5RiQyB5PQP-N5cFJ368c4N", + "name": "Invoice", + "category": "doctype" + }, + { + "id": "7zaeU6pqVym-6Je3Q36XNG2-ZdBTFSVwNjc-pJRXciTMP3B", + "name": "Grocery", + "category": "expense" + } + ], + "removed": [ + { + "id": "GbXgszdjBt4-zrzuLHoUx7N-RMFatC8CyWt-5dsBCvxaEuW", + "name": "Receipt", + "category": "doctype" + } + ], + "itemUrl": "http://localhost:7880/app/item" + } +} +``` diff --git a/website/site/content/docs/webapp/notification-01.png b/website/site/content/docs/webapp/notification-01.png new file mode 100644 index 0000000000000000000000000000000000000000..b59d4730f67cf168884317d5bd73083ee32894ae GIT binary patch literal 10651 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 mAIxD0_ss6R&0DgG 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 BrrZSd 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 literal 0 HcmV?d00001 diff --git a/website/site/content/docs/webapp/notification-04.png b/website/site/content/docs/webapp/notification-04.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1a25bb6256e23e60958c47f59a517a9418aa61 GIT binary patch literal 187656 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 literal 0 HcmV?d00001 diff --git a/website/site/content/docs/webapp/notification-05.png b/website/site/content/docs/webapp/notification-05.png new file mode 100644 index 0000000000000000000000000000000000000000..4da60ab48d0bc2b2daf7f0a405195d48238ca0ec GIT binary patch literal 235127 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
(HOKzmJ~no4_(;i4t#bm;hWDI(%|5%B-*KsD z*w2g_R;oKjuER_KIeO2>4V`1PAXk9)?sbWD2MjhN31Jds8cwK*8qos#w4{3EjMG$N zn~7B1N|=)V2y){1q+mthTPL5dvGqHpRI zK*Zzkvhx;!4}5v{X>U>)mG~iUR`zYsTIkqwCh&NAEo3I}LNY5*)Ms5*H|Omg>X`5I zQ0qNWO)ud%#cQpgc-FEn^Qw#@%Wq@RN`h*4EVJoMD*Scq)I^TlknidA6VH**F50Gk z4=R-I#{FT(+D#a=JhiqOTyzrC0UA$VJoC{@j+=5fSALf( zz4buzCeH~`f{3a`6oXk1;BNw0`v%nI%w2bU4dbYJ0WgiG`3ki|lCM*3ct2uuqJ|b? zR!%jlQ3kZr>R6VaR#|?3Rp(5(O?oP6`+*kZ(#cPNHI-fE&g4DR(C%W z1h_GeKuYTYvdKV=Q~`*F;i;LAosEMc6p03180)Vu0aL21wVqp-jgwT+d&VMmSZjf= z^Q60O9*hiGG{{dJZ4A~10Be%u*sAOc)Ixk_0z_ovEYR5cJZdnra#=vI7e;fNB^wTk zrzpaRGlT-wFq9M_KuO6Et(>U$7lkJkrn_xnj27$b2{?#l}Z4^@t1H z&9{Y{fXkyh?H)^WeFRhF_bvGwHTyF~vWq;kh|}3tB0hTaiRnah;v-J;}|_T_3N~*06y7RM|ROK6?TY z0XH0KeIsn3ne*cjq$=HnMFc727#-Y#cssSUl33NWhTRQ$nn|QXp|YbFCqI;i*u@MG ziE&7qRY2bK_7}@TxYA37wzq+<8rDFt1~i`FQ+hEA>>WS%@*AqFUy8Q z7pmU=8p6Yxa|-7VIChE?`Yq2m{^hBmquBIzOv)KcsF$r(`6_T{e$Cv$&^*F+;~n$T z({twMPi`gOKJz=y@6!iugMQR5k1d>ozTHC8r%uzsOxH90;EStOkQ2Or({+jG+~@dc zA@IZD&%H7lb}<5w!Wr}*M5KU2kA2p2>-NYG)(37wtG|nO7GhmTN@v9EPgNc~w)41$ z8)VICsXKC2<+=4#UCWcEH4vRX;lH)9xw0Ae`pvx?A53X}(3LT9;|Ft>aDJr6)*g+v zEfGtSCx{Cz)v;l0c%WDjQK(auxSlUip+ILXdpn2t&G7Pl16k~E>w0%_Z!pA~8eP7MqbMnLw{2Nt*MM&VsCo z!=5`6)e+0}Dn@6MBNPFmw7l@$G^=~>;|zVrw0l(t#v&#OC>!@{FmSN6r)j> zW8=?_rmGjSvyfYxn<;?@RHFxHGn%r&bn;Anw35d|D_@r=@V~2n1yVt+buyFAqe8s+ zkZh%;`$}8sRueNqJ%Fy??{yL%vxRVVfTFK&*FuZW>b$ek)plK4)>va+v%`MqP9F(N zrQLYr;uzYf_SMqUzAgS;{+aGx*1ED8j|~nV}*xXvcL#Eib<|zRoWfdxxeJ?jK3KY zP8x?k@ex}(8FZ#H9Q|~Il7XFcWBJCzI9?npSyJ}M`@a&^yUiJFlyBy`P`!oqE&I&q zV?VVX^QdQFld;f!Y{r==V92xWZ_F0?T|g#Qt{;51xoze1-i|frK4Z1pK|?>tg8 zLuzFaTu%T!SYgNTU3fG!oFSmxTF#ftnLCu#-3z_ znYcrLShBtsn^P@CBhKKVd^=a;N z?MQ4Fa>&U(kD)o+wSOUbm6Ar)#YVdEIRH?y{|ybboD4h9d~nyoPEk>jwUX*|SUB{qQaUCA=7B7cg$IczPC44|5I2@E=u4 zOSe+fWngs#2*k%VSu>Q+ngd5iwMAn{?8EL4RqAj)lO3~TPU|N6WZwR#%6Ch$tT~pC zIrNa{Xu8G>jdXkBek9b~bTORqfM#aDgI03?tmer7>XMdO(SL})Ut;^$c`~0S~kr| ztR6YK#daLm#2hcN%S4`;RQV6cwH2T9Er;W8jm2f>S=z?2!OnCR2jQk!%`2z=XNOk{ zk@^w92FO-AT!gKz&K*tGN#EtVnD5Cd(G|Kd(_sIaqVLe`eDN?=KdI@wx_|2U$e1oC zLv%)-nb_Fi6wctYc2t_5?b~duo6>|vl|4b8)r|7Y8yp7^4WkZfFaLB94v)N?hJC1prA~ggl#8WqQZkSf5Npd4#TWy*&$ZVHr0=rHMGf3r#*S-B z^Eot*2SV*|Jw=iWGk!Azp?%qQH$!FF9Uaarp2_C(TfNEt%%e)*Or!byw-s!e_S#o~r*;2I{|AM=kQ}l0o_<;lG{ic*iA4kM)UevR> zToxXIHlMdQ4f(;8g}hqdzpr$666;38=WzIatEh|<-X2PYdoZ>TI_s@vf?R?QUUuIH zVVBBlmm?$B4V=_9jkQG=D&T7)jylJquKX#HfoB6Dff5#jRkyBI{|tDbbjo!Iw0?xg zc)Br?bcWcD+{-^Hd_W#+>ri|0wWf;3I_-(YHT3yKZw>#mOf--FW!1^vrOSZeo?VxP zUr>%Or3=IACaMlu3^%}=PCEmpZua`48yPQaO$^D|%^+FXuOxZ64M1S+PmJ%e{M-DU z>DhpM?t5~i8&D^2X5jFvih=G_^CFou|jc{a}51&$9P; zNt69#w|e7~jV(9L=zdyqwNl!n6{(4*+_Fjs;ZwecMiLihWp;r;I#nq}Ec?O>4JuL6 zQafMf#;b?1JZ@)Y=*&gvS6}9v+8JtS$Pi&)f7~0I{m9L~3uUOKCG%`V^Q}5VO^5D9 zAQ3ccFke62`c$e=M^WEEdnj22SZ?L}lb`OSyc(FE@z5CxRgc``Zp@9C}qCdPg*xjw%31(#4GmejNylEx#Q!kYDa@sRRbkjCFEa~oy|LD>0$ zR$kTv66VRCzvBc$sB0yT$)NaV2zfVdfAk9x9r#6`nC@!s`JWH|Dn(f|9tYwe@sn%M z=cqp#IDS!*q1EN5YNN*NtlWPlQ8}u-MV4MO(%g`0=9u_<>qM*|S4m%jN(<3o(bkV5 zLAi)@{yYSSj2!-fN6;e>EK}a?@O%Y1Wik?xh2ghR&uTh)M6jCPSGxTP5A?`@Ae5bp zWH#~Z**m;=C|xm{4q$995e9n!1bsaJIDZFoE@<}O%l|I@?>qiKj{aY7`R~8~@1ssJXMr{)FU;#- S$v(vV2n9K1S){Z{@c#jtdJMb( literal 0 HcmV?d00001 diff --git a/website/site/content/docs/webapp/notification.md b/website/site/content/docs/webapp/notification.md new file mode 100644 index 00000000..a8e59927 --- /dev/null +++ b/website/site/content/docs/webapp/notification.md @@ -0,0 +1,205 @@ ++++ +title = "Notifications" +weight = 60 +[extra] +mktoc = true ++++ + +Docspell can notify on specific events and it can run queries +periodically and notify about the result. + +Notification can be configured per user: go to *User profile → +Notifications*. You can choose between webhooks and two periodic +queries. Webhooks are HTTP requests that are immediatly executed when +some event happens in Docspell, for example a tag was added to an +item. Periodic queries can be used for running queries regularly and +get the result sent as message. + +Both require to first select a channel, for how the message should be +sent. + +{{ imgnormal(file="notification-01.png", width="250px") }} + +# Channels + +Channels are means to deliver a message. Currently, docspell supports +these channels: + +- E-Mail; you need to define SMTP settings + [here](@/docs/webapp/emailsettings.md#smtp-settings) +- HTTP Requests: another option is to execute a generic HTTP request + with all event data in a JSON body. +- [Matrix](https://matrix.org) +- [Gotify](https://gotify.net) + +## Matrix + +Matrix is an open network for secure and decentralized communication. +It relies on open standards and can be self-hosted. + +To receive messages into your matrix room, you need to give the room +id, your access key and the url of your home server, for example +`https://matrix.org`. + +You can find the room id in your room settings under "Advanced" in +Element. The access key is in your user settings under tab "Help & +About" in Element. + +{{ figure(file="notification-02.png") }} + +## Gotify + +Gotify is a simple application for receiving messages to be notified +on several clients via websockets. It is great for connecting +applications to your devices. + +It requires only your gotify url and the application secret. + +{{ figure(file="notification-03.png") }} + + +## E-Mail + +E-Mails are sent using one of your configured [SMTP +connections](@/docs/webapp/emailsettings.md#smtp-settings). + +The part `docspell.joex.send-mail.list-id` in joex' configuration file +can be used to add a `List-Id` mail header to every notification mail. + +## HTTP Request + +The most generic form is the channel *HTTP Request*. This just sends a +POST request to a configured endpoint. The requests contains a JSON +body with the event details. + +# Webhooks + +Webhooks are http requests that are generated on specific events in +Docspell. + +## Events + +You need to choose which events you are interested in. + +{{ figure(file="notification-04.png") }} + +You can do so by selecting multiple event types or by clicking the +*Notify on all events* checkbox. + +Each event type generates different event data. This data is prepared +as a JSON structure which is either send directly or used to generate +a message from it. + +Additionally, it is possible to filter the events using an expression +that is applied to the event data JSON structure. + +## Testing + +The webhook form allows you to look at some sample events. These +events are generated from random data and show how the message would +look like (roughly, because it obviously depends on how the channel +displays it). + +You can also click the *Test Delivery* button. This generates a sample +event of the first of the selected event (or some chosen one, if +*Notify on all events* is active) and sends it via the current +channel. + +## JSON filter expression + +This filter allows to further constrain the events that trigger a +notification. For example, it can be used to be notified only when +tags of a specific category are changed. + +It works by selecting paths into the JSON structure of the event. Thus +you need to know this structure, in order to define this expression. A +good way is to look at the sample events for the *HTTP Request* +channel. These show the exact JSON structure that this filter is +applied to (that applies to every channel). + +{{ figure(file="notification-05.png") }} + +As an example: Choose the event *TagsChanged* and this filter +expression: `content.added,removed.category=document_type` to be +notified whenever a tag is added or removed whose category is +`document_type`. + +Please see [this page](@/docs/jsonminiquery/_index.md) for details +about it. + +{% infobubble(mode="info", title="⚠ Please note") %} + +The webhook feature is still experimental. It starts out with only a +few events to choose from and the JSON structure of events might +change in next versions. + +{% end %} + +# Periodic Queries + +These are [background tasks](@/docs/joex/_index.md) that execute a +defined query. If the query yields a non-empty result, the result is +converted into a message and sent to the specified target system. + +For example, this can be used to regularly inform about due items, all +items tagged *Todo* etc. + +## Due Items Task + + +The settings allow to customize the query for searching items. You can +choose to only include items that have one or more tags (these are +`and`-ed, so all tags must exist on the item). You can also provide +tags that must *not* appear on an item (these tags are `or`-ed, so +only one such tag is enough ot exclude an item). A common use-case +would be to manually tag an item with *Done* once there is nothing +more to do. Then these items can be excluded from the search. The +somewhat inverse use-case is to always tag items with a *Todo* tag and +remove it once completed. + +The *Remind Days* field species the number of days the due date may be +in the future. Each time the task executes, it searches for items with +a due date lower than `today + remindDays`. + +If you don't restrict the search using tags, then all items with a due +date lower than this value are selected. Since items are (usually) not +deleted, this only makes sense, if you remove the due date once you +are done with an item. + +The last option is to check *cap overdue items*, which uses the value +in *Remind Days* to further restrict the due date of an item: only +those with a due date *greater than* `today - remindDays` are +selected. In other words, only items with an overdue time of *at most* +*Remind Days* are included. + +## Generic Query Task + +This is the generic version of the *Due Items Task*. Instead of +selecting teh items via form elements, you can define a custom +[query](@/docs/query/_index.md). + +## Schedule + +Both tasks have a *Schedule* field to specify the periodicity of the +task. The syntax is similiar to a date-time string, like `2019-09-15 +12:32`, where each part is a pattern to also match multple values. The +ui tries to help a little by displaying the next two date-times this +task would execute. A more in depth help is available +[here](https://github.com/eikek/calev#what-are-calendar-events). For +example, to execute the task every monday at noon, you would write: +`Mon *-*-* 12:00`. A date-time part can match all values (`*`), a list +of values (e.g. `1,5,12,19`) or a range (e.g. `1..9`). Long lists may +be written in a shorter way using a repetition value. It is written +like this: `1/7` which is the same as a list with `1` and all +multiples of `7` added to it. In other words, it matches `1`, `1+7`, +`1+7+7`, `1+7+7+7` and so on. + +You can click on *Start Once* to run this task right now, without +saving the form to the database ("right now" means it is picked up by +a free job executor). + +If you click *Submit* these settings are saved and the task runs +periodically. + +You can see the task executing at the [processing +page](@/docs/webapp/processing.md). diff --git a/website/site/content/docs/webapp/notify-due-items.jpg b/website/site/content/docs/webapp/notify-due-items.jpg deleted file mode 100644 index 85ab4e05ba93bf5a66b3ecd9c1930323ce1a05f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238293 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
4;K0UId#q41IpFJ73r@ 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

Pde)xWC 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%0A(ePsa`c(AjBs92^Z@36 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

SCcSc#_%W;tnBQUI9TXF;;Za#3b(xu7vhS=; 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 z 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

q~D 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 CfufB7 diff --git a/website/site/content/docs/webapp/notifydueitems.md b/website/site/content/docs/webapp/notifydueitems.md index 146093ff..7a202726 100644 --- a/website/site/content/docs/webapp/notifydueitems.md +++ b/website/site/content/docs/webapp/notifydueitems.md @@ -1,6 +1,8 @@ +++ title = "Notify about due items" weight = 60 +draft = true +render = false [extra] mktoc = true +++ diff --git a/website/site/templates/overview.html b/website/site/templates/overview.html index 3ebc3874..3f154ba2 100644 --- a/website/site/templates/overview.html +++ b/website/site/templates/overview.html @@ -36,6 +36,7 @@ {% for section in section.subsections %} {% set sub = get_section(path=section) %} + {% if not sub.extra.hidden %}

+ {% endif %} + {% endfor %}

+zH`KP@i54sYg9y3Q3fJ{f(yI+qMGirte8V=m(IDyn<%l>J6J)_mMF2xc=3{6Su#Ca zsv};5j*a#VR-ej78wQ&JAniik)PRZQW&*r*AUBm;A^h}^n8&wNJ~_a7t*6*lvBEA` zhbqNZAx@dXc{$65)EYjCak#2XS6CX$bU19f5RpcxTRJ2H)rgQLXL}s-y}|u&+gCppFvKw=d}z+PG?Hm)akfne#b&YM=J(ww!83nu6k&<>E_HYpzy} z$crS$c~RBdSk8iGk%W`jjMnt;KslQva9dl@POCoD;06e_OU-+JlN4_npFb?i zkgwDoa5j9~V%T2N$GCjNU^e}QIkD*LMg{&$MZWYv93Iq&2bce=_+SjZ)^aXY+xWO8 z>n{et1zq+QJ+~(AH}rCBPrSL5`l8`_!B)ol291NgNt6;L59D$R{ml* z|K3hI_bW&Lh@Bn{`d`2!cIg3(JowRUD*lLhG8<1geikaA#J@FfG`tqDSz?_38QaLV z1X0r=I_<;1P6@mIp-(yB^w5kfE?b zlh)cq)>~OBT?^VnZ^(P3+27GmrnS`mo4H+n@Li;$UXm)8V@ay)t~kN~UgL(%y4Q2Q z%~NF0{hZR7pwz781xm|!Dk8^eQPzdbDU`-2hw?+!BJb!Hg(wd8Qr0i}HGZuNU~>za zcPka`wS(_pZx-=;jJ`_OkRkKJr-*4#wfn;mS({tBYx{Rs$c08VIHXsj6BKRvl&jrJ z=`eaj@y~qSOKo=RLvvZ77sY@WX#=>fFAoYYt!Mz!lb@`h$+TxXJr)GaA#FyTkt&Kmh zqGd?Sk`Jp%<`HCkNu7pTc7$CkUIG&xJLFgeKJv&t3lu=yck}S3=l7mcdRl>NYm{h8 z$b@U))@VKfQ$W+;(*>lG4P*(GnEu+h9y6rPl8r&umK++&j3OhNGPLwDKdrfp z$G(X$xiBK4EK;6WVq+#{?GQ|AuRr*nmiU)W5>a4)>&HgZx(fIl9GRh>aul?}H^(BsV{S>0r{ms2i;pv!?ke%XG-&hbOGK+UL zy4a27SWk#QvGLV{>BPmHMr&Ad5lL)f0i1Dah;!!bu>vnI{SpcZ$%C28Y}OZd>=5C& zGnC@*2|pd&PpqEgURN37<=<*dFjZ@`TToB0YVap^^T6^dn2Y;pYNQ&tn)_LCU>=k& zY+N$9$0F>9>*}PRv`E0k8vEU)Y{(pq4l41J@a-cdd5&!IM}l;!(apM=&|#&foLF+` zkQ*-FL!C-;Mg+QLfh;oaL|}U@87iD6dE>OJpHX>)DFIvQsTx1KpWkcMSYTZL6~vpK z#0OmmLQ9^8sXEff8j-u9gh?gCkTC|V6c0DaAw7Or3CUmB;lm=b+2erX{6T#OpI&m8 zzG^6aYH<)&A?A_={^3jh_k6YPM90QN9jiR36l8vh#bXN$H4`Q}+}jffM8j04toeR| zYK>r0L`lXvIfwb719Dqn^>F7`PfgHlosPxK6qg|$Tsa0N<3ny*V#{4R9x$r(Q$HFK zDg^PS3McL!Tslu%NGAmjr^Q=#Gulv=h%vT`8?57^kLsGeG>24wt8|MEdup}1y6Pb9 z9WX;TX;$g=ERav=(7fteg#JqswngsJBHR4q3v@`iRH`>|EiP)}%~iTX;RP$2mqnpv z&hDA;i6JA{?|kQM@oUFN=2?a2OTja)Us7s%@qh8hM`MRSoD8lX|5NI>=J6hRCA_Nh zU5nITaCJt2{MFDxga|o};m6zm=5G1-tnp8b(xY)d`{x8D38_WnAD(7BWG5wOsH|Id zwJ_A5&Ch)rlcv2gB~CIuQerO@4j|dNhKKBVIT&hWTFNOxxr=xMq`^gar&4mcBE1({ zx>&H>&prH&&RzJ2#XzVAlzWG$q;joJ3zcB+(cak$AvM|u7Q01*qido9@KsdxeVffE$XvzJ_%=}W zC)0iDL28%pkDOQ9%)hMMu8)EhQfRYNS-OUX0mPP94bSlO&cFZK)VWWCDnC#7GC zu`-zwTw~wODW{Wq5Di=8I(H-bZKqbyJD_wh9|3X6i4X|llr@abv6 zT(b@nr2DO^Y+65WoNLY`$2WqdA8mhwGVx_&HEmJb!6#F!ru+b_^lmXAY8vPYu&p}W zF`kNZ#*jYapbsln^XUd=;-X}CQKR{q*TB< zu3f~oMnl+=%m$f=(qr49QS5CXs^8AeG%Ot`t~*eCZy~2`D5I&~lg+L_%TkF7n(owE zxXl@g%A}}H;_AnSh@~jE(f5#c7S-mEAUsuP*~V47d?p~4^o4SY17-`rcZ9rrlqW_v zv}6mPfGqiyabh6dMwJ!SA?@n`2HL^hE{#{}g}lmd6eVUQRZTF<99`;LsBBYAPQIHG zza()cRiF5)IaO$z85K&EV02wjY)-jQKguwQkzVfS5yft84c{ovqS;r-=qA-Gh8ly{ zXSQQeX-+0zbU`&{05IKG54Kzk5-fjaF8$^DrBSLAJkzE8MzDJm48XgKNSeE?;p6UM zqWd^9MLqBAh}%8yia}wk#FexYeY7?3gjj&wi0>DciL0ag31{h|p7C+HswiGU{7;J4 zw9n~q8Bn!n$=G|Ja#pd<+vJiOn^5e zjSt9ZGDEUV7{o&9FlrW4GYw^`^33-)4HqL{&G}HpkwfZ;AiT*t67IG-G05jNn1y!f zszfqACgYHnP+3EA$`i?|F&g6p;HD3IALTT)>vgT!zy$$oHgAZ&Uj34;8#_|$HR;2> zpeEMFpX;@5Tjmf=J}kf;>b-%(3@g2wuuU4t8OQnzz+6L)jXcQ#G*O#IbC}y!R#C1iq1aY2vmnJ_ArgLrg;1%i9;V$ zY$>LG=s;hU>#aa=S;zlu^8Mb49~kgw?Vj;jDkY6b0=x_En0=!fLi~yIb}{&q;v3Xh z@cs|fo6CHErIxC8iigTW9xY$tCKDd&??Z{DKT@RK-l+2(HfgDHD*M#nXK*AuI6IQ!9j%fhHz z^bng1P<>yq_icdz5Ess#C1R`^(*PmqYqRW6<;R?Sc5E`ZFRxTi&}tAz7G{KImJmVk zwFy*nFvuYhb*cRACGR*gWxOeiiz3`_vx9CpO8#7$)m@t>cA3>dhDrl1>)ff-teQ$R zKfKuarT+hXEzln+Voufk(+gMSd)1Ff$5hL?jq~HwZ&i7|uQJlrt`vMDz~QQ&&<(FY zoTdnW=`7Pt;!U?7Y^l3ydl#_WN-tUWacbJB+LJ9*6`!t3Se_r?&fp&>SQ{oytUP@9 z(U!Dsyd_BE=xA&SWwEcXqs{Ir1l!@-qMs?r0x4^9NW4?lU{OEc|C2cxAJR z)bjm=i;>w2UzqMDJ>rY+PB7X}e6+S))^K;?=;gVv>>gLos=S9?CyBWts0$~{^{x{T z2=vE1042c1@|;Hj8AfkOcwbPgX(*V}_B2H$A&@?gBNG;y9+P5VOx>pViX|%I*9tE)p|k~GfbRKyBX&9u8O-m)|rF$uUk2DYrIuf z-GFdi3oFJ2dRKQxR!#D^@@Z8ts;F@gGwzoY#lXWRSQ0~w@9@wtIMgNt%;FvJjLVqO z4Ta=^9SPFHUy&zVuLkNL4Yk>1FFUX7M#R?*M0(n^7EwlSzE@&(s|flHDZF7En;a8c zGpSBHcQ+*yD-@M0j+qt_?W3{@*`U926_jUNrF!*e30>2XK7{ zd)%}6zxZ7LG8Ciq>D+tj-ReL59Fk|(lh{2txI?1#4qt-US}CVFb6%P@ce|~=?a7m6 zYHV`~=d!a4Fo)%0gQk)RtCeKd!Jv-HN*LT8TUSMiMxtHGy9Jh%w8mbS{#$RM>j^m_ zqmP@!+d&WglgCP!Gn+dgrmVU!-l5GWi+3p_%CmKYs%`)hbifIb!3(~SK9(Xvm9EUE zmiuQdQPHWg?(dH6IBL)+CC0LZe%N@sPmt!r6?5_K_d4=Afq&uubJpmRh}&wM#>CYW z94Ms3sdGxWC0)?;CWv!k-)KS0Z%LVLkR-|5-i8xX-K7fsrifR8~DCyIhPQ(wB0hK#@+*zCGO6Q`kT)2Rb z@miMJCl82qgpuG!qivefJ*1~{-U{;vIyy*WacUAE1AK{|_>@|$&Bxs_CbgJLmxKP^ zHv&2Lr62wOqdE$Q+jXDFjp%W~2zKA!ehQpg+!;s}-4KFk@Qw_Maa%Mxy$H7dn>#sIMLxn9j zP&I1P&1|NA*p?tm+wjrbLQv9HTE8!t>TeMkb4o`>d{%Qg9my^Xx#kpxVual@e?T4l z)7G9WdUQ^xUxuwW#paxT_8Y8{`8k#t{T1fr#pWs<8K60 z7Mzn>oI}o;jXTumte6KmdUxJZ+?mm^%iejB%;#BS<~7C6?4{aWkEqXG&<7N&J_3U| z$frQENEudLkT@jPyN`jt8I5Bg#d>JzTQPd7X$mmCR+7iwrh2RE8Ef%QTB4HJc*b3j zF$nNiUEiwq(Da#)aPhNU1@8|kS?rP+Hz2coEnIh(5_i>vT=lcl!LOg~-8Q;eg4r6i zUP|#zLPo!cSAta64pY?d)$`;PF3%);NqWpqLwYk*>P<_Y*kJ-nFWQ!a)SBp6V#)+) zv-PGiTboA7Zje76m)_0`)TWuCaBut8G>+WZ360%sA^V$VY&V(iZA`nZq(p(ob(Rh6 zbs%axXnjwzY8 zjlJYukOtSFuE!wxjzdcz<@`cVS6hEWx+nR$jbQ6Chv|1I?N6z#-mfWC71Z(CmFQeT zd{cRegS;kCi#j|t(G~o#`c(CAMYX>^!wx)F{+rI!E-ZNXmYAkaL8t&A8=G?S$uGRV ze0<1{+OsFjElR?rO$v)^*I-f2FMQpkiWg>_9q)v<&2zbI-=uoRAUCTdLG%%@Hz+Bj zVH1_A%)u^~BRDzT#r=Mz?pE@S?ceILbMNhr_stfVO^)UebKvI_VeCWf@xyNfr(yu4 zP4HbQl+`iit@)XZ37mjtxJpzFP)ENt$F1CQo;K?<`EGk0Ce|=i{7rBPthvaFhmh#e z(Rj<6Ul?suy#Vb(+H%74^PZf|^Dkcz!^e>44-6Ed>;F<2zB*0$s9jtufI@ zuCUPm7exI}(YnO=(|>=O#{bC_kNTN$Y<)1iebu)Vlku|0I3G$!5G-BYn0+q$yfv$VN}(QSw+^Qg0Z3j>V-!Y z+zlToxQ(G=s4y>YV*}>~NDAshj!01Xi5?U@%xIHJ7;!jn!mYa=uUttyq*(Sy;u5oBoMUv|)de4w?t@d#i zWxOYQed`;+olt*z{z}*3hv$4v-j5GWhb-tj%DGgM6g}!ymon+__U-nBhHK(phgvF& zv}L})iTfW$hV3~?{S5h}dqU>0<5^KMM3|=Jgxm~% z!_6c}+pssIkpGk^E4^205&f3mQSF8h(5Mvjldy3t(qTDzG{$o**O%|LP2Y(Bd^&cb ziIa$$C`wKr1FNAE?uXyYS;oZJ#AK@E;Gt40ekg=$J4XiM-4aX##@M;tYJ=#fxMNfj z^NGZLcWSnsOf{z*z@$nUMa@@Ic6}hlDP$EV6unL@Tp8CV%2butLtP##6upM3Ftav{ zfErOR`^~()Gb@<@ut!G02G*4;wHC!}(@WM6P_tGFo3%ox2_-Psog#Y1=l!A4JO+K^ z4Wh?Bk!Gsn4Kg1uvTS!zy~3eI&eMU+-*0qUCLktM#)@|STBD#Q`S)DwP8G+{H+d8% zX);Yi;Oom$U$_zyL~0z>I6awcY#~j6du_E357^v0JO+^9H$F&hyy8u@05TWYbpE_A zqIA5W_@q{^17my<#0@^Stzm02mAw2FGsgMhASv@YHBnDJ2pNUS5-Mm3pff0BA*W_ zHQBHUMxG0OS@qlDB%Uw@&ekg~xEKsBwx#4Sn*wP|871%!{-`-)3p#^WfEu>j*^gdZ zNc3GRlYnFJ4w?4F{_i0rX~e0GFLDT}-#1`0yLwtIWv#$LNt6<%UP=QH}tsnFT00pjuQ7( zyN;|Ped$PgRzi4m&7_vhbx3#m%b0p&923fc7t7O~GQbyP;eY-l+q*V0`)eMuN|aj| zP3L>1w{N#kH(OX6i>j)Sdb+x-+`m?8S{b|cT6u@J%q)R;j+;F{e+4_bN#M>JDqg#qW5g1dfihNg*&Wb|M^AArR-|d z0dvR2B%-4WKTYt(0+ljk1V8;maP9lw&5Li}7pT1Q6WLW(VMS7MHW3yjh{ZJ_Q8!BV zhq~7(epY_s{zB}R8?OMC&$EADq4MgLD+*UCd*)NElZ^gvpO53u#|5utlEqG~sl1_~ zm&QSM9{Kq_zRr}<2mOrw>=Ky1Gu!v3e=OXO+9UT!;q$4K#Ww;GM-e}vb~BBO4o9k6 zYPa6*Q-_`BMhz+%A-f!TsohuRRXkf!aG!UZ3nM{PAL4Zt!mZvhT;c1jYxqXcwZo8> zkR7=WyaPQhO)1ZVzz=|Sn(HysFWuouKjoNJWPhpp>KB#u;;S^H`n)+I^WB~L7LreQ zl6U5!Y}-!FxjGh1!-t3LJk71mXzaew0pTBssEcTvW7ITVtD;(nK9AZN*hIEWE+0-% zLRA0%a8ezvM|0===Vy7v#(w0Xi~>esRT!E5$fyq5Bi4D#r+wV-#Owk3KmSi=&FynuR ztg`{`9gufRC`;{;fL2v)Q`U{xD@{wcJAdeT|<`&)1e_i4L# z*mTw^YG{$22Bt~SO09(tE+r^mVKm`b&JX8FTnDjQ zZd3_`ZYuL|9o1xf6SIpvx@>fRYA?ER=9{$Sz{H*v!u<`E08OU1s zv+&MfoUQ6aQBgT@U%g|i`=Ak!Z1X<(S`4C`o<7f}vxQMAkf|fTS(3K10_eD0@p(`D z-GlmV1Ff_w0~Z&d%E6)mf1jUS_=kYqBXgT(!%!DOC)ND~HtiP&JAq7XmD$TFuY(Qa zb9~0f?5TR;GUY*}hP-Usf+Kg0kseLM-$RUjOF2mW36 zi~R>f`T~V@^``}20FkQ}A7i=&^Ou|q4Bxu$rpmM2U;gx#>u?IzTz&r#ZrAy=H1Wi# zEa%hpiq({_$cq63zgE}U13E|HtgC5a=-XJ}wp@csIeAnQM+vdJF?$-5X>Oe4PbW^w zV`0$lux+`HjcJ%>qc9EsQa5Hv0dlOKEW0nxP{KoMS{CIK6%5I&Lh|M;`L9M-E1ui( zd_L0=kuSdR+HEWEk%b-a2{rz@Iqk2BO4~ps0OJnok!v1@^8!8lOcktYT&Nejx$cJ& zq5&Mp%Da1Z@3v@+mqjjCfN4E6UuwowW>WN^_CySO5FeMtw0j=|DNY{vtBRPnWDBk# z@^m>r5Epuf8M6>{Z^T)itD{6~oci_n2e)GnXFDJ}Jt~0w* zZr2tSb07*?X0i{YIgVHH;L5Pte7qt}W+tX{U$1w(TEiGQGOnFx2_;b;9*2Q(cO~X% zCgI*{8k3Rx(<-~vkX)-itA4G7$^`LrfMDSSQ<_}0e`$(Bl7#?N2}+4radP?C8?@M? z{K+YC1@*G1Qa*fInY&s?lIb?2EF!WZ;BGNV)G}vV5u5aFwnl#~UGs?gIOKcO`J&Cc z1G(G*yjXCR?D3a^7F-K*pC&$HEoT2Z!d%{PpJ|q_`_#luHS2=uuPs)Ff0&DC87$8% zc%M9+ObA;L*9t`9jQATgzSL(9ei5_0;1R;PJ~&;+Y3xXrE89@|K4XW-p=^K_W$voe zlIB`1|EWheh{B9lCCH{(oareCHivhYy`byMha zIEwfSr|06n5yXAHljXvlxOK=exuAJpbyXG5o~DMVb!21jcTT8<+bqc8OcHqRW01^x z)UGN0kmQCLdcjJJ#US*228+oPwdb z6a^VZRbP>CM%?|uF9UdI`iGexgza49@96Nrmszv;l!8$c{3tE;nRDgr@>K{9v8KgZ zO04y0&xc)$xc-yXe0`%B`BdnI;tfaE?~OdG=4dV1bj8Gj>s?`0)aosv=1j&)IJ)u9 zG;xXoTR|O`Jy5{2$S-Hq=i1*0zGj>FVwyX@bAO6-H<^b+50zlJ>e?-T6D19|RY8lzG+IGp*o@nr-J9)1wU-zS+^L#-XX?#V z&8wPMrBa(sq(iq&H3xn(@aNr-^>m+Y(d`A37b?42ZbuNzD;MEA0h_%oEh~w!iuK z*Ojc>$nD0!Q7^kZIO@56%%UcT_B8Au)^T3F1S9o4 zev>9#p-04D56BIY@`Z^#3q3y|3VOm{*jpQ`woq>cL<%rXBBSk_s_C@7l>_cTd$t9q zfLd*H-fVyLsKqX(-_~^jT40l6kb0>>EZPekr!F$MQ)EEn(VbQ)%JbeoT*L_`m<$&K z#Vg_2ZKXM&x=DcrCLL;n!Vz{y5NjV#2HX*28aiY!+0Lang3ugV!Wnu|9>garY2){# zZ6a6P@{!eGSAkp0B#t0mYG2d$aMVxtGZ;SkhxMleCp`owp2AbGg zIT+9NWfp12HN?Vwp1Go11W4?J{%vKHekBe+VJGse;jApGWxzkU*`}}&g>SPV#8>k; z*LZWBNxEXg%*lC~9O{U!oOk|Nc4f!_O)K5r8prq`R71qz-kO!Pfbw*Tr;=|EdJl2M zbZ6m8z+m9p4urSLmlgUMowqQ96z?aSjdc>zRohxFLl#L%jCKyL{$7LQVy&=RiHvnv z@28u0X_6BL2_wP4_s#&&Wd)dtP%k}s+uEzUw?c(>Ys~>GZ__h4qKu@S@uhhu>eyrL z1GJ>^&RrjLh3)3SK*oNo0Aq#eUlhMmXwa_4kle|D`9-C#auz4lvUli#YmTEbP2_+t9uStWIzvBmX zwchpSc$;PWB33VA6*p2KDW9iRqB}_#?l=+=D~MYYo(7ro0r<#q>508ol`5pKatobF z0~w*Mc{U>k4*PzrdRq;C*QMhTZC9*n>5+&AAwi4*hY*y=vXy5ZBPVz&wbCH&Ip2Af z=Q&}99Xyp@MvjsYs|)7F@b@mr^wsSfe~b)p%0-B>^q-@+zIR-oS%!?3=R9)lz-QY7 z3)dTW+tp5aF#ypVQqLk>4z~j|kPKl;v`EW_y}_Ex-^EUcuUtfbX9Wb+kcmCgvcRCu zv@{J^We@2zY4vntVG=u(!>~W|!c;W#X?5#(2XAj_yWX)Vn}8nI`P-!GQqfbOKb}pS zqX}_MS+0^Tl#1-`eJf5gC$x7nVX0aLM5dQ_<*~tO<`riuvAG)=}0#Lmt*G9m!1zS?r^dF`dG!XJ6PJskI;NJ1+&a z-uYYy8^Vt7+|tHHl!ppw;~-TS>rL99-AHhtfma}&6`bM~vtqqY>mZ~(&1`^74bUw{ zH_U^64D@r>#T_wCkZl_nll#BCMG>iAV>TA%zpWv<+kwSqVl3#o6#XdnoLM0S*S3gx zOxwu#jqZ;9lIoG;w|%wGJ@GX<3co1q1v@XQBPXFdzOnD2r`r;DKU?j=X*gIk9L%N+Z<1IJ}3`X+aP;}^w725?b8eddaH5xvx^ zLtK!SzT~{ru&4JH!f<7WOah?PjcBklokg^z!Kkl9#HYJvIkgMN($ACPcB@!3FdS0ZP%xv`~&+awdfbuI=vUvG*jNHouOKO2{yC?C3x@Ei=&RGldqFlNl zycG)k3!9Jh)7U;+ARW0k>klC@u%P||X6`imks5-s04+oAuU zf7`A#+Xj9n3eY93LD&_ivAIlHN#`!0F>Ye}rTv#H7Mt^twU&q#GoVc%K*`K)aVKP# ziy#g6mP_^p7|O$iOzTHNK493*_D?#GybP+kF(c>=5}DHY^wr zGU;{**crGfn!mAfUG6w@(o+BO8|3Xt`aOIAO;T0O2~aoDH8*LpU#-5cwo!vXEg6Fy zos!~uXFH$&r$79LMVL2%=slz`wn)~AzzVMABRM0=;qu%fWj4DwD2ci8o1Q!aFqC0I zOYjhZ5vfz?`2ujgohiBev6@``X0j1^T|46oFrA)JoNg5s(};mtHySb2HnIgLDVl0AOSmZ%jQy z(|NZJacjQBc@WKuH5(wC)v^F(29js|g@4D66RF+^lC?(;Tm2C&oJaWs5ye~4koV^K zA+~~=O%p}wq2v=foA=iwLa`><bIr-`QRC=_Ua~-<;d!yBnNodykhcwPRq& z9m|Mhts?>JYWeO&g%#d6tZ}2U<>mc@;SnXD5)=di?kcO=JuLIlJM~lOJ~c_(7-exQ$KF1sb=Un;Q{& zkdMPepF#aO&uwpH_;>~0uDZ?VYEGFy!oktH;#?)lUSn+c_7xs9IGHtFJNvk$UvWq5kl>WB0Zy^qs>_qmq3Rzv$#7(4ny>)8)|&wm;_p}5CFT! zC#hd)z4LuC86yK&0e+=A6kyuAq~?x^5E=FWx~sdKw{%yCvR)0_^ka$6)FKDdxe?i1 zdbu%SS6y%}g{dI!11=GRbKwU&VSu14BQXS8-o!$pJ0&BEo|NDqr;! zhK2s3Na%-9^;O#3dlKCpAr53%Q9=Liz{AAEqokkA686x%>e?oVjx0M$i0!#tRc#g* z2$2x@X70sYJbk=-=1P*f`QUnDanwCjPCBGoyp!mpyjx|zdieUdGC>e~f9R|^3Bwsy z^dW=QzuQSokzR_vTC<>^$GdHqqp=AJOkoy1sw9x@r4READz>~>^D*4{((IElj;t3K zGz-=HeQQM<#u^uK0ov$RPFImf`H6-)Rs>-y{dZw}RqG65kPL=zfK6yVOxt6)`S~v5 zc3P^-l&uHM<07rNxFt}37r_|3*}g837|?Z;!86aYa``yXH?$I4Lo@Yc7W(Z1J3=$d zV;*{8PklAsq?KYogy)EX#)`|+e2>A4@v zQ@s;xP}91ZvnLlbNKcnO6j^go*rIC=Jx9SKNZX=qw|@Yv?QM=P?^gpo0%iB70$Em2 zwkY;imA5Y7V+c`N&nbSB2r6Rw*q~-`r(bzPgKjsl)9X^Y1tSWOK9uZDb_i|u8Azuq z{zV};Epk&)?0a1cuU6&OeDb)7%?tDFa&9@ukrQITsz|_WRht2}5)RX?MFTW|R(10% z_^&n-0aGp`hQ{9VF^ltx27xazA=BYS9>SCHk5$vsGY-auY2hAUA6YP(%=UR>M`Blj z8ofC>Y!{$(_L;P~@~Av|YwRAAp+3hpjiTO;Bz7JM3&6}I$5|F8SguuTFbza-OX`v1 z(vPVdD{CVC;hzAda`~+pmic1p9sPU&t0N(8TUSqCc5J>{GK*z6$1b>*$q=b}Zry*( zl_PK@AbTX=lTA<7Bcd_?IblIcshqnt;%N-cTO#qc^ug69UmqfHhN{_4TB<971`8*b zd_>xY{`m``z)_^rce=e4DtRsQM1`4wT4-lNqc#-+%X8JahI+@_Rxj=Um`zn}l687M zR0ye-fD3Ck8zpg#9j?@fBnvBTZOOzuj9XNbzE#7DyEp6zgrc(FFowNFG^T@mm&@9! zcLQO8dD~Ybuda2hlpO_RS+8dANl%b zd8Q^;Be1=HO~amDL<^^+CRxA0ZlWp>Xb=@C@thNNt)O4SHHU$j!R2{lW5mgWgUw#e zNT17>Wb8uD4U2wM8y&{0*oW6%y8P8 z06fcRlE&Z2;!m9$m4oowYF}{PtM$ipBM+3WJKs6wq=aVmEoU@vK()G|s-hErI}TbC zD|hCRi!|Cl!^3RN8IhPbv@QEcbm%)^Gbrv*-4`?M?wh`4WrP`p29%9XlP8XS@#*lz zDY>EdPOhuuOmdJbg(l{o?FF2L9DE2;f2@o$UK`>m1} z{nAT4ne$vkxqQGb#!|r$<*KwyP)mznu;}gsv{YR~fYD|g@~yYTt=*E>Q~hcN6(%Ce zm=YnJE-sRIrHh!zT3mO%mL^Z)J*Njh zNj}TlOUDO}B(_`D3uMFg!?k|b~LT-o%xwr~8MLvnAd1MlY^P>oRK(1+soztfuMFmNV=1y-yj2eh9u z^HZlZypA{|{I#May&v!8uOk-GVLkCq=-}q*FN*lK9&cJ9a8ohzmAIjrz8R+0u>zwH zy7oEiiCYYVhDGf!N`YHN3O`S>#co8UkEV2!Yi~X96ANO}a}Ou-bS{#vBd=`UFAnD& z7=@CN;jTda5Hlv{#eaLQt9N4EHIHhl)`14#p`GavOcQil3xz=F0~JSQ2+!@OBHD_>1&GAm`muHdC=TQ`|8b9AQRh3&3?l#in^Sz zp6l`}Va46I%kIA@9RJJRZrJuy8{X#({sW8u!S+vWx&NKIyZ!IX-TxVNNB;<<|A+Ex zGIK{M@z)1V*vD`G#@zk(4|9i$S~dT#_?-WO>iK_hQ|_6=k>Ud@C$>j_T6-e;U>(%# z{%}jxrz@)iqZJm~T{(S9m*BHKm|}ZJZ%?O-;TyFpuTrP8)Nw5Y(|B|=&yX#KQ{|9q z-KKAv;rL^;;KI$Y=zFWDgYSkS?7FnIkO==q#|XmGhvLace;F2nd=*&==~^U9_fDglRzM6!SD{uD6X0} z07}gv1GgrixQFgZSJ|GpquZ}oXuA@12m97EUCgd41Nkri{D-z#{{Na0h1#Z^Z2jj1 z5}8}73WyCF1D(k1S8m|Xckv&l@AnfBOvWI~`_dy1U_K5gy|4>ZZ=KQ7bU5pJ#s`UQ zb`ze)B7o~&O1lo0!JWvl8*fM^^?T0llk)@bWHFtUjznA}uwNv&tBHkr^4wm@kLGvl z?esy>v&fV_Z!`v~vKel42554`IOuA{F7z2L57AS%Oce^2K4viW@8no(>=Dk7wu}a& zgw4AqAGq#$gKQ{o5)|0B>Q&6@1&LF=85>R&<}<%2FqjcvHku>K3y&JAcXBF?`+HTK zu!>~+VBDWCzu}NNcYAs}F4Q`LW)M7+T3!9d+LL~<64r|2Z#!hW(qfwcYaptdBpOc` zxa((>=-1f~N4D3)XWvL`D!di%N?7}f~UI z2Wt&=E;E)GkBuaY{YPja?<=Go(wTQV8}M8t?RZ*(S)$FsC9`s?Dn}mJ-dLTU%!%;x znrG**)$8FaOESlicOvtPLLD=+^`EoJ0 z?b9klbbnudve44t5bgs>0tic|+~RVHSn-!!Y7pvLhTg5wk*%P?mlEZ#SXuG)hz?p` zx5Y5BA(e6`Ef5eWAk4x75CMkxeSY*+4onM3#>&%yEDddE_`Z@=h1~m5yn^d%^7o5+JI$}@9GF{lCO%RJ~hs7D9gwT9Z@1X?$ zs_GhoWGx?eGEd38G#!*d$wIDkakB)&M`B8BiNLGJf9a1d6Q?nMhBoi#n28M@*0U@O zHi?RUJNSui82NBWJz`v|!@U3Yk#J}Cp{PQR=)q&b=#0P~Y30Dsi^piZU8i|NqL{oM zk$x9N#L0Y9*Ud;-4E5WdnA7Ss;%Bn^npXWbUG$jIJ4hfEO6DDgT$PsTynEC|+NCG#zXm9oLolB#?HHe_B*(U`}REOO_mJAYBnQ40}0(JR}cAByhU z$(4mm;AC{fKnYlei4if5bHkJpt3n(^YIfkg1IR}hCS%n|Y3jh~iwuZ{5Nlz^k%xIq zC2LkzG6gvUdh%K-L!qC0jvt|CDxkLQGU^e!ij5XOR!-SU3OV8#%Sn~iK2pdXsF=Xf zxyH**eTh+D+CFM-!Nio}OAtLYk6s!Z;7?4J+n-P?p@BQzgV!Ws4$h5WJ_0e-mx^Sp+H5*7Q1`u+?@AhSdn&>K)@XrKaOAN)+H?-L}g~it- z^^2Z@^wa%lhdikka8s+^6R%t3T$Kb0ssYlpSM?jCO*OTnqoclX$aoAK+UVut=cbC= zBQW_^QS0*_PSc3J)Yg<*{=(QTN=RGBO@;KiDS_s{1-V>ChLfEs!XC%PL~p4_V4nGm zdk40Rpw!Q=5ZV%!_(mrODAR7Y?CQi0so%{n3+yrmrpSu)A@@ zilm_DY>qNpJV6r$Z@r)_nTaQ4F#+0N6e08lcw$P`7wQH+S_`VIDUCxVt+R+;u4(a% zLdy>G=m^*6HQi{YNvliH(K!30oD9{(_C(aRDHb_6{XoQBR$H_*(`}$x6LgfoG!ezA zRxJ_^3_|S$afvyW&>WV~lj-`l9x@|dk>7W$FJWf}jhKg5f76P6Uxm8A5SE~{d$U}2 zPA(ougUS`&o`8D#rL#UHs}r7zOf1Guh$t&n;~+Wu$AJY*zGyRG-rhPWt~zMRv2=)Q z&=@xgshAaV4IT^oZX@4d4;x)5$Z5DdPd$`c%{2iUTbZo5s18V zzGao>!U~2~=FA*&Itlg?l@+XA4>KMn+nm2|$s=2k>0N$FCE?qYVw!0YN7#tT{uV8{ z^On#H15oN=64gzuN=B}27^9Olv1mt4c`)t}N?W9BZJ%=|E@g|9YUv@8<_R!tQAx;+ z+ro&JMr$SHA{rx!1KR}lnZ=K_&l-bhgMuGhgFAL=n)JwojUyN6WWPmSWb#A!?qJ7| z7P|b=i09ynJ*9}=+IFaTgeV|C{K7zh+j>2WQ7)Y1I+~&+!Ih%%qzZ@8L*(tLc&c}p zyuiu!LMv>jhr94Ba3g-WnW;aCQ75(buTxQp!R`R9Xyl)`-mmRSdwJ&$O5Epqk`}i} z@M^sTe7v@1QAj+kQV;cQrGi-&uq)bN;?IYOVU#pbj)-NWRlqF zj>Sx?5UHqG^5-zu+q4c!jJu53QR9#8E^T?CZN_L?3ij||kI${h9~$AiJ0YVjqdBDb z$`+_c;8GrWEcUe85;tmT)AvYCP!^Q9(!Z@WD@?P-m52@B{MHgFZ0YI=D9~Mi9BpF2 zuH16_tMr4j1aQEeqcOUE>QP-j+J1hHp8|#IU0aMH69Wg2!WzE9S|}H0!?)bA_cMD5 z;aD~@TjU4elxR$p5|M^`xSdF0B}Y`HjYAj3g)`L&9tfawjW>*_nb{atUS8Jm8kV$N z(qdYDlM9_Kx~J_?4asS6mAY1~;0K0nU8^m~4eoUne-SW*R5rAhNNJcc=J0C{Jw&&q z?Jhz0YZf${fyDfzgKG5tZhMXJ*&@vgGM^}M?i2)?`D!jLaV{X(ph&-O|BVIS;F!Z^ zGk+ZlYQ$H5*zh}(Vv%c?l0Ki3jAxq-B6fismHZh)v#eE;a(HW;?3%p2Dlw@Q~hmB%Cs+p zy?cd6aTXw02v?93acGTqay$M2<3L|$!m+5ECiP^Xms@Cur*nTUO-|3HZ744U zG_pRt(8E4xwQ_%%#q22JNv(n1ib0oja|CGK$>MlAl#2WYxy;3~9dD|oz5d=4r<*L7 z_xvVaH63`xsMLoSa%P>~{01-EMWhAg_Q`_lcw0-^)JgnUf|hQ9XepwVrrTjmVwJ;O zYPG5jmB9*7f--zY%Xg(SCJRNhllU8UoV)DF%}b6o0VxJ~A=wqo=%PCs+u(UzEpGx+W7yKIH>%=Hrqk-aK!F%01Urp5 zQsyGpMxIyq;@1>5YF#-lQgDpMa>RTSpT;N4`dpLxqTKN9D8`hdd>&v51o;uNL{V3XD1C9$pUy<4| zV+@gx?Q0aH*7&OpFzguUuU|a+1F~B|CLxsvQ|=8`P>27bVBhTU^dMDtx9T5=q%^iM zGz!Ku0)I_wrd&8vmeIS!2uRyz+tcD{j(W2W>F^lk zx82^!s@#zLlmPbD$c)}_?6S0}2Bw8WrgIKVQvR8{B~Md1F%z&dxxcVr(LMpgr}xqC z+O&GfO`r(a?Gt*dG^>{m`wo8O@3rzGw?dYMs6ahxE;$msg=9IH#Fw_!2I`9(*|5L# z5*$P9WSc!%NTp>dAyG@@Tga*1++pc71gci9PZ= z&`Ys^QQqp_H7Cz&wY2Quy&#+GE7rvjhXcR&0S(PPX>Gl84VM9B^VgIvBERp8=6Sl~ zM%*#G5^S5QN<;YSloBFV=)OX4%A|^1@=j;}?^BjtMV7tKXd#<0o`7J`59B#!JG zfR1oC_*Uu--l)Wc=a+Om3mctVNZNj?CoOL!`(ShxuY4d2jyQqQrY_g{Be_)Ktp6Y3z=H} znho|8xHzg&9_$=0Zky0&td=W26uqvTh=q+@Kj<{`|K2Qn_PSZiW~om4k_&hgxzRNj zk${LN$g7kwRUZ}l* z-Y3vqqHL8c?5SI*2c4Wms(xHSTlQ7gzpxDVELrmRH?y7v#Jq5@^cHs!xHhfCRz7`y z!$Blm>a>=Ejr!63Lt~5%Cv@8?M~8r>$n(fk(YKKwrL!0&`!GIr$yOXJGY z!A7sTvhC2DFEaj48I4-FvB5rRjI`xe=JQ0CrKQFX>5g{wTOq0s+|m9V0lTeddw^aA5^n-Vf+tU9Oz@G}MzF7ee(~-p#*%hBo0a}rldc(TF{F|<0!Z+JuMcb} zblb>+zi!03l1*+kY;{TM_o72i`OG)JsOk+jfAQT3+EO^;U z+i$F}2awnHL`0v^4^Cp5h9o!}lK?V@=@u>`SNgH<6V(E#O*)k4L;8U5=D;`0l_AE0 z^GwdsD)HvtY#I$0niT>d9Y#q0n3t1+tQ(0;C66wKrJFPwt$qsY+Hi^Zc;+&6uefsW zeE?X^-63%0aWUGw8v&^uvkOpP3|~2xmJ3l#kC_#sjQ>S(JM98{NWFhi(kT#$Nqvz0-jN36e;rm5VmUYGh zll12jHiB~vS6+HN_wXX?!t|{29>(ZpciR|?zGSrXS(*=SxiYlBMl8y<+)1=xsQL$Z zFpk|iWluyvcxRfBVaa(hTf7BDCq$q?yMOPQEsEhRmDJmlXp0)p-QR}}j9zu76Ihz% zWKV$%U%3D5ZY=Iv?`N97HD}lfHWFs&aUk80>F3qH?iq14Rpi)CzEF7ft zW0vL@x#!nICMRU#rSS9kS0Lg6e@FkD_*hCaST}}~Dfg@@)AsShu5g-h(W1u{&b``# zd}wN#^U9%s;!XUD3n;|7czgwmmtHgUg`gMHiBQlRjA0{q&%B82rvwjc$}xKCv7wr{5}nE`*LtM1Nkr!^#0JJ7 zrK&AVZfK)2wFbeXPCBrt)(qVfRyMlcUtDg5LHM+(r4H2BDaE0X8H@cm!oVF4>I9bO zTu3~>Y4%_#^i1-3irfM)IAulCva>ddE0JqQ!()yNZ>cm4TZWbEPRwAeINo5r7r^Ik z6KPMX(%Ez5A3B(7S~3UNr7m7;1zxHw$nS~IQ&h!NSqL>$hec9~Kc%(EW=L^|dEQon?Z$|n*Fc85 zP(a^83BCXDl|Ydw|G4`)*N&w9Why3Z5oPN*5vzw2NK)~2BQ%hhTvPFF?p{499neL9 zv?$Lw*rWY58LD{;pMHLr^5W3Y%0yun`Et=Z)Cvq2dMWoVO-$0V;I>K3NI6yIYK}e7Or-6L49w;? z@_eFO=apSlMfVbA=os9G_jQ|mT|GD}Qt#8Xfo!mFt6H-Y&QeD!uweLYMikiAzI>tb zqdNwwxgb>A5c`YzEERO4e$|{dBV6==Qpbg4J*Q6SXj8!(y1@?LHcRHcytqx+y@kx| z?oNy9#se93AI@61=eiTd{t2GRv`Q>=k=W7;FW6JlKX-o=t#IQU>2+At7*yB--6G>6z2R#f zVJ;DgkK`3b>xQuYjZgBnl(*E}k$&lLJCG5gJ6vl7)`%V+dI2rcs|bQm>BPL)#kS4g z_JMVSwv4&ulEKDawa;tTFKsAI@it!Fjfk9>6Y69E}M4aO=!v`j)YGx1#d+Ziig5 zkAReoDsjrR1`6C6*IP3hNQBDr?%62q=`9z&br(!mMhnm2cb8(33`EB8McZ0NQyqoy z*9m{+iL~o|PjBM5cof5dk_INe66869c($dIVhmsNMZkxx0gQRqRhQn9X+p3_xRG(uiWBnP6%pZk!%zpqo3;NH)n{sB~ zZ$V_ZwZ9s*%O|?h52Ah;^0;`aax@(6!Hzj}4h;L=f@aG5q+$K;wua-9#%ji{j(Uzx zD8Y0)!=j_!(E@CYD&?zD#I`-Y0V$|e?7*+}7vPnT*y1zG()V`RcC zz9hxg`0cp_OiEg=);Ay}*1c+NV>GwFhOQTK!1=j*=(d$cDUs1GHd7ddh<}4Z()xFd zb+zx3&^%yEr+_HiH+l;}h&qlu41mF;E)HjU-3q0`o?}o>@Q}U&i7Yi)7)>{^77R!6TlsT<=bmcOGa- z|HoUpoGxmfftIW_pc5S#BUn=Q=<{Zq@R{{fMjp7A3jOn1Q?%MA&_)<+`KxJ6=k|@T_gyg7eXSv}}At zp0uD6*se%LSHl-MJRs-*lDnm|g>b`{Cjm>^~#maIf z!T4@vd}rz^Z*(TyUxWh+;IVw#;NlGTWY5>-`{XvwA>+YndK`bWsxVH^t+4(raxugU zrl72*x;kM|l5rig;Cnw@&)f>Y-u59IfmB~pCMOokRV`H`4#?>>JI708PbA8W`MY|G z&ux*K=_`=Q&73J2zieW-CRZiK{B3%;r6}-M^_m*NO%bLj@Zpm7+#E22>0b)$3^e)u z1Vn0Jt71#~o6KHU+}Zh0cS;5H`UkZuG5a4F+MlG{utLusPUi{cDeGl+^oQ@IuacuT zeo+`*7yhD%I6M=r$_ryf0J@h~APFgAGBqm-pnWs2ZywyUS2Oh>XEl(G?};r+MtKy< z|GyqcuCFqE0=QDl`F6l;l^P)&9WHSLgaBB$ZwqDvxe+|Zw^?0Z%C@pHQm2nIt-zE# zh{y*9(d;opB`A>_m`M`bonXQN{nltf&yCtm+0A#?q}eh%NUl05&s+EiqTE~DK}N-8 z!W$bkbdy)OQh!lY1a+KWG0#|`?$t*t2K)EFAFI0hy?#|NO(gi5+4@H~+qc$0e-n5h zAf7(vl>UruEcWR}puzDkibq%Zxl!x4J;wgGJ9nw|OWQE+X^KDF0RaMmmfk5oFgVD8OLXRImW+UnTqCj(KS)9}aX~ zCcg$n>HS|6jcgfbK?|6nE5$uE;tks==r9Oyi9K(NxbD4L?6_I`uXlaW+wO$KFWU0`+stR|IX|F&%^#No9&q_-+$7obSNE+3BLC5s!`QkG4^U6(4nuWBp!=df{QQgP)8HzP-#vW+x-8 zJ9mn2G^^f89acUcE7Org+SB*{i-@ABfhcKA<;>g}IOk_$TPP~pV8tBG)asDKAiX?_ zmI0bl-kb&fyA*CphErv~Z9kybdBCew8zUq2zV+|CUQ0NZfjCB^3rT9f*iZ{;o(qfNGO}{<4)J$ofui*Q!Thq?+`ILmArRY#0&tJf8 z7XI?!c@f#BkE{!_&QT0Qz+zv}j?<=`8 z(&ZQ?8`&6YbTf6^X52dIyOXZY71c#7Zf}dv^S?{9LqS1m-CC6vUZUVG*_$UeM-kaG z>nSsq+f_!B9if5Ahiprg-CfbObz?>C*gU==r&;Q+#sOp**Ca<46ZO7Eo_x-y9upk^ z1VcrI;+Ue!q8DYog~RsS=kRbw|jolHWHlVjD`!CGQgH*ijot*OpILijXaQqj|%e{{p8wL`y?^d(yy}js>4C zkE4?6)4nxTTTvq!Zp+d?=XeR3Y7XCymx}IFPd+-{4Wp8A`_sfC%aQmwR!8&q3La+$ zmG^?42_V+)-16GGbUt~E2l$IZf0`Xqf!?2F;p<9bs`XP+IyT~s^Y1r> z>Q9-LR(4qw|cdVItt6A$`|Mms+ zdyN0fIbljNKj?1TO3FH0yU1D5d4~sS)jD}BSn{9ejA~eG8Aq4TzEK?GR}tF^NO0%- z#<6Ae*Pk!L6hCAB=`4zky1FMHNH>}hJ*Rw|u~VcTN2E<%bJg4r(_L3V?=Q(O-wZtc zMEIW@{(t^Tw*QO%pc#-|ck_m)C^>z)5j2}}_r$j25Q8vReDOd2LLqOE07(;d8!;3#C4%VE?ZJvKK*eV zf( z`UiPqjT2bG%4AWH;076>_hx+!#tE|=9Grs44}U$dldy{}6N6Z5(AvX&8_j-EB(ohp z(iwamuB|jI8@WyDaTU%;uCvBBOAVAxwl-K$=9kWY`jl*V(bjkl&MB#Ee~eF;KI?gx z#b08fp8edQuTXpa4Fuk`%-FvSs1`TxP_HfKKD6&yRYCQ6OC(gg2GeCMmDx3EShht! z^gPW>cUG-Y*9>n_xR_#w+8?_FsJFHdzF5XDM{9>iWx7C*SQ=a$%>9#@9UL`7qW1W_ zBHJSKt)kdlS7w~4+gk6aGp5PB`H|o}&tCcMc|`m>XzCcqVg2&^)W@74%|mI~)H{Yj z1EJa*o2zwV?S>W>UK4dFd!E{a1bR;Gk3&KZ4Cb;IIM1w2H7^v4mr<8xcl->zO=#ZWeK{zBF`8h{67o<3#rBiDi39GO2H@@q~->Y}%y#@tBxSBRRNc zWpu&<62zNJV=zpPW2}xJd|@kqQIhHTLoVJ$^Eb7 zM0?Bkb@x;X;&{lw{{bD-y{^AfkzZvAi(OK}#gCDl8hmx%L^qgvN?HEB57;f91xXUd zfjYk^u2EF^Ygqkv(Hg%)qx{Dt%mnR{7CDU{X2F%a%@pD^+1y>v}>kcsdjecdj zM8Z*Cz{9gu7Rc!O`51S=s~b2u-NE5_EXiDghM;+j}%XwFiZ)8z_IOEOB2(5 z?-({kTnpOaC2-%3v)_}3?SaUEVW9wv@9BnR70of5P_EM02))RBmx;g!~jrG3PM>tgab|h%&Bo=IyJT$F~+Aie#Jy*%8Q#BFUS=%7w z&tAg1eaWynTl2}WlpE2w{-Tuy`n5*OaglELu+`ZkvEX~@K?E1#)l>LbRGfxLK{mp? zu0A*FO3z?FqSlPPOc#bI8#DSD20t3?Q!kyg{UB(9>F0iH`{N=->F2WSZO&J7D_B%yqp@VZyuwZJwJWB zbMnY(dW0eN&j8tuh+N+?F<$CQu4&{!| zQOBNtL>y?56W@QcRnbm>d{L2{4JANZUCegPO}4fP%mM$0vERqjV|Vb5{tL-`&?h_M zYrI2L3%~QttD>T$0bVr5?2Oa)>Cer_YJL~0dOvQki9T)l|0Ax5`>sbTFwshVh5qMd zRL1+|R+{t$VeQF%e3GQ=CAoDjf;WoFUzz>c;E_Z4;A=68#7+EJr(0Mf!k%DPEa7S? zpf3MZxs?&Sbz*N8NSJUMO{)HExMg)zB`#qSKRA%~uY}dNCRT}75S9$10>ei^Y(Hve z)2W(jZ&@}A+*jw#I{aIQqtJ|J6rM%T`3`R@=u=Ud$0KOx;0eavlZ{82BPlH;ZgKpf zd0Ihrlne%bkx1`UF`^%O7a$(@)qDR<%a^ygx-aVSc^`~4i-N~bN9fgUyf(#*FMF)U z-e!LFh)tKeXJLDL^ApAGvC2@1OD^Xk%DbBB#ivcwxpJ);p5a zB}xR1WN_!BNITzsvj7f3W0X1F=ZWz@SN|mDzT>rO7}L~NKs`(H$c31iGvV0kbKYF=hZ&`^*%BPaGy9@p+>8CmU zDb;^$8xdYCIU(d~o5hxeZB`~no;yUJ#X2H0uwi{DW%4jAz7g`3Wz*5JI3XTC!kPY3 zFu_G3*D20KpF@}-lp|yPR^_wAImpU*034UT$)f5WBg~@l>Z^9MP!z97%=6{@n{Rn2 ziDT_8{4pFfNjNVP3wKl+cVSk%1N1h&hF2FGU*MNS%kef7^~S;OUr)J{%JB6P0s^Jn zifebSwrMs>n8x&6T)zh>&EbqABhjI<)C%JX3>$+lhIkct(UshNT?FPwj5sk~jUcs=!?S+45hyFSr?hixr}OY8ByS zul6*ZvoVW%=OfKsy-u)7yM%pKc$R3DySCEI>&{wI15-`N#MM)%-?fD zo^K~%Go4jxab8cg-ks&!XK~~}`M>2i*BJhd(NFT94!s?hmh*TjE{qLEprmB5#~bzl zn8!Tw-&rTmJ-f%vpi*vcjU2EWoR#?T=p+6)s*g`5KMtY&+kE8Q}E2IXuFS`ocDHV(44O?j1M>YPpV^Zwka1Aq?Nfrfg;p@V}N1wEB zH6>wnzSdUAHa{bnzdN7xE3*+h%6*PA>Tlo>w3Bdo*ZpvEUg{6y_K%KTAaHGGZ{F2p zCp6->mPs?~XnTA6)AOI=*4(cqZvDoNTdM6S{mlzu8L*Oj_%D2qcX3PNOF2it@ZC3} z;Lid-%D^$q2I+qwMvI`e-}`BjDs2tcS#(}!mff$%Q{bO}a%Azfoos_b3+%Cmq{7M< zNrvgEV@$EnWcxQ(o&UvD%k{RboB6RJLwfpq+j)Zt{ucL-bPho|_ZkQcW`7vI0X}_w z*j7RCa*Lcy*1A&^VV2S_aciknfBNvgQPm?uC8KGKm%4gBzESjfk%O~oy%JySA6mxT zvkXBRcLx$a$?oKe)sKH};1KeE_C#Kc{sHu2lfjxI!|Fk^oFg5JtX5bFs!OCo;?qo& zk#W|3cWg$+y7PbQF4?An_8`9XySI_c+)1A|E9cA=?6fy%=0D-`^PD+Aj$2bz;?KnIjhhcWVYyq1GAnQo8GA6)a43ZC z8QO{BdOgiD)?#kmxSWPOO^z76qn0&SG^<=w*>LgnW1MI9VfH))lrJ9M~Y z+xMIMSB`#uc^k8ocm5#Nxy)-lK5;>eXGWP_g$S%HSQ)^Znu|vw{(j%bAF?sISS*))Y<`UFKm|Y%-xsnXgV)E^{)}PyDet`J z59_c0U)X!^pr+dGUmOvYB1lIABE5tnB|$(%K>{fh2_!)1NPy6!Dj-;pVn9Gz=m;SJ zk`O>jq*`c76#@ZiDj>aBz=qXl?_s*R=zq!Br&zZ?&_OrA1o}IndTF+Xa zwbtjUCi1~y`G%8=BJ~YfQa>u*PXr5e9#9ld*1u?Vf8bR+^pD#;`RDES*8N&I)WC(1 zaoLDNONRQx?mw$-^eH6DMccc+&OhPBmIdZ8f>D_xX73CQql`0!$E?Z^p&xMbL;!86 zO5{0a8F4OfL%qMb6R3X@f|_(Y#5O|9#TjfPGWgb;*=XdoNM+SWg{a2%I(o zTM=29u7vaFbp66@1hE`WpFe!>y_XxM0oq)}D<@>8%9gF9&2}MsEzUjNnyz>X+DIRr zJEdSU-u=EcHiVz{NDxjxyWnO%Y`N3BBFWB~Hy-4auGVs3)<{1Hex_U`!gs)29G_O( z)e0(W(IH@pm2$)yyM?+|qLfPFHanNwnUN=^OqK%6|(Z=s?I z({<{5IpCa)QLBfOg?%S;RNjKo(79Nj?4A|CJv!RprlLwJKEtDMdD`T_UQH7E_%Ba$ z^Zr4F2C|B-_26q0Hw8;5=#Q$k z&xY}F^BI8kknhOZD2qpUfe6C_GYoFro!WokfF>CpVMcHV#laiYzdW$})7%!4pc4 zS%|2ZWwUy#BxYM>(bBo_swFYw4ZX>=7OgySs0bwt>fHz!OEMo3VHz?Jb~c)hn-5lWI*zcSP(sKp4D zaO;IHw_A0Ih-eFdu8|imjnY^4}nqQkH`rt8s)lPW0AY%uqcsXMU+wnC}HuQKt1N%v>;@Q$8r4=exPOY zJs>y2@qoAKLk5Ko3#fTHszXnPy&9&>1kb#brC+vxa^eJ~CbGS|y5-vKmN6H3$lPF| zTmzk7&?cnjP;!J>+Gv2KtCgkdMBs?ky)?B^xS}V<0nRaQ%$Y*i*iEfp4&AWpX-&I6DyzbV|LsODQ?JvWL* zYO~KZp-Z&Y42Y?vQ3QkfCT*v~Z_%ogypJ;x;2?&2PRe=KiB&miEi0V;&Zzt*BhH>vZ5X~MG>zPE+mvo}?Jt++8IJhr`q zb_&e$n@^s{M2txbfz{_Z3u_E<*x)rFQ&I7xjWU2wp^R;AiezjfURbKvoK)-tLB@s- zXO6B`DKw#nTYEg{vZNx<8IFqsI;{Gf2{=u}PgytMPu{XL~#|QS28aygP2TSYw4L@jj@DRCk4sQv6 z0?$nP2WgF0WJKHM<9YOvU+HaD)e)B(_ReGbP6aqcv?SP(!9W{*)4jpgnHO4n9k|9y zWW=SNJ*_2{x2estw;$ea97+K=J4ZbRu@^?qCtp6o%Uu~~+DP-7)}LyGlbXZrkKepy zCe^x=AsUrmKtzFsfu`A$`tIS?6d@iN4JL6z%rZRA;B$^3`4Hs>B0ZM;tK593PefH) z#j8qJtR4!3u!Kd1Mck0j8SDIE8sJE?2eC_HIRyl9b>eR8#`i9yv9?0!(B;GK-L>j_ z5%!D6`Y0}Ml#YBwiBp8{f;RKQuFpgS(KVJNl5&qzDpkjlGWGkh{366)UVbr?(~`|o|8 zObSmZZBg~|e&xrY9b26u=3Y0W>dTe+eY%`mO95Adl|+Og>MSnrqwvo!Dp5DJ!A2wr zt9pLoHEK@kX`t!c`^fTo82vFSm4O$Y8{B3X2_2SBANiip)n zAMa#S)+yENqCb}lAa&TP! zeMVU~w@CgIfnrn$d*Tbl_8iI%g<-kRr?PY|n~UgN zv!{5J6@|jz>xw|(L4mAejn)Tk&wa0S2o5pE%sXU10MMyon{ycYZLc ztmN3`T8(pjYq z3yz6dQO(kn#%&ZUAPbGHqe2lTjHED~9%{n#F5PJYbsj zFgWfIur#b%bq-ot)XHHuW?+49;&BzVpsgJGa>o0sH_q)4byRp-Q$Nxyxqy?4#{>*= z@wcfE(rX1R31F~2Q6_#&HSg9nOPp}l)B52;3m1_vF(H$hkV$|?OOli8O?VZZUws@$ zRRTHp_1hQDYFT2o$?&J#nMD~P*~Q*2ibY5Kuf6;6<%&qwSPjUwwjr2vC}>7{GbEj* zH?wj^0!?N3*B{6sm+_sGGqZ`y3h9MFMz66lUsOFMS-7fQZ#bq#I!c!0{i0x{kdjGL z1+8~{`AXMA)MQU~9?vqkbE3~@!lSYWNT37Bwu{0+INcm^tko_cr;+iBg0i>6nHOEQ zDTtEdQ%hDvU_yaf#S*La`^kTn~yk&S-3Gq$n5lwcJ4HCF{e9J#4hbASLf&3G4DIh)`x+R#~=ir~8kZQX+<$XlyC(NOpf z(x3ua>J{Lf)Z=Ssx#6CeyrO!hCe48i_GEq(sGTH?RtM?6mR^l)vQw#6vh zSz1#Q2CDD+7DqrF#_kUSP?A zPwE}3YqhdL2#bji@nNo$&X6i*b32{$TfIA^Y$9r&2=*h6AKWxLmavVoS$D`N?8x;; zz%zi35Hw!mko3MwFk48y|3ygc*OV)BUfK5xfGR_ym{*JJi{E4vK3Lek_4h}T!P17&iwh1&x z<^RN6F$gS?KL5$xX|@CK&1HKB% zoDbGp&ua7pRK&^}!Sx+$-yrNnLi7{Zt|EDa#aLc0^ysuIbqUTKs^{obENrw;1*ql= z``I8JM@`zOoE{Xp8)lY+3R57CjjOMXQIK^zDB(=wVD)HW=S)2ZXEp>A9@3O_-x8{= zpIQIznSoQI9E7_5`%y&>>qI_Xdg)H+kcN^d%9^(q?+#jTpJhQuk6#5U26rLX@!dfY zKMv>ptJBn-=$4Oji1mvH0u6Ir#6dGLz0o*yEE7WTu!y0F9Eu*k=ZMeBvkMWdk#wzD z@6E}9RWv>y07nlD$%TJ(O`hsiBWCCVJ6FU`! zTQls%c2YHG(p=Yga4Cs|{&4!wb4KUnAdf;0!q0+-q(GvpRk@b9_eGxJWS=ba0mQj# zPI(nSzXF#3;qQ(oenfTWgd9-?ib=S|@W0;(%gU;~dz3tM8*A^D{Oig^g>iPTlvqeV zu<>>km;ud=_eF0lJ)kGJ(aqd1Qm z?h52L{2NCM8W)sjZ|56dfV*8#kZwrjfFMnpGN!K7-!@^W1#SSd^`7s^9 zlMpCZez41}M)n${pv=~b?aKjgB~M{*{PHwj4swNEK{`eiCE5K#D*Hf};@`SolPQ3?g6IPmp6j25Sn`_m=(3zW)E~<1HtYoBfzA7m{YV0{T9pypG z70M@^l$h4B&``b=@7veckj<4Nhr$&iFl>)!FRY4nHOOkHID%wkHtGB_k_LVx^6!&zc6Mo6Id~VF5!{0pCsbJi((W(qJi#w5} zCGj3wBB-WUPnUBuakxAh`Z@XIfUL&R?7g3hP+z5uy;e{7*EMw2D0=wh+$Y&G%Ub~< zzx{RJ@h`h2+Xmpw^R2QBl}3~^s|}18vn3(7!X``@^wVRqM4Pb_!MhHgv-j;vm@rM$d*cwqtSx z2|20Cx}*eeOG>#%9n#J${ziL@N2-WcMd(r3n{v4Smju6J%{{Y>(fWRh9MXCI1d6JM zs*nzTlTlW^gIs-Q;pAjO8E3Oj0i={PR1B2-JQcksoW+Z6DyK3KN5Lvt8V%K^tF1&= zZ&#Z;549xBq19`&gKNec^9%6zvU4OhWIs(pRD?l_*A zQz}^lzELdLZJU4foqnrWF197Z9>8A1a-CU9P@@|zBKkOM&*bKpU!*yy5K~O?NzP8f zwu7`MR&iIF#3Slc-rvh0x{j9Ce;ZTP+%Q3yAF{3O2YvhX=_b!n z82}^ZC#O{{8$)p5;a^uvG$U1XY&bBlUXU5wAMdM|7&Dz?3eZ&I+B|I@IG$NHVd~oo zNKRu0bB`MoN>g#4U_*Y9bQcs>D6RWC5K*%H%d z#fRidD3Zx#J+@Cp@#a_s?0X9-v5@&9UHgNL2_wCr&gyb_^{oC|b5$U40yKmLIMME2 zJxZ#g(oR)8G5!r5oi=mf_Q{wCG^(JQB~$ENck$1d_1nV@p?sSBcl7VnGz*YX8xGj~ zs2j&5zr7mBB8a`C?utd%kt`7du(RcELH%v&3-5~i^TvGUO#dG4ZfC;;6C#M6MeT*c z?^{_FBdA-9raw|3u_9uZU0iMCMAC+DJ3>OCv*i(=EN^k=mQdvHb28-eee1@kK?8%} zj31%(xOsuR!rCVv8e=~s5Oqy3q}CbMzEB`a%e~`6$60t_OXLNSCRP5={f}9fo!p_P_@xl= zBI$Z&WYE(5bOj$9L#qcq*PpU*)n6*&fM~yXVW-~s41>E-XXi?W24Sc2DJz(-2+$Jk zsY*1qC7y_L$u~M-w9tKJV z&lyg>*!KV!I`Yp5Yq~O;;MB$1W5+K(iFUCGl&!l4yD)j*l8^d+-cnK8AhXf5c!aq# zwSvL<%?Ml=k^XSu{>?gxWrv7>HwQH@J6F(b_MW-rd$8)$_%t0QRH@@QkUYDZPmsJN zro~%%a<+@r8S)!_wR{#^O^Un(Nimz;pFTE_;dnZ6c zOulczGm<@hXA8*h`&+&=`}J}Op)MnH+* zt;$+e6)q)4RLeIAxG+d}F!t#B2stUR=ZF*W%rN!SexVtcoXz?VO z{`f5vqk)UtR|M>4QI!C=0dq~X6#O(K3Y~&+e{u>|AG67qn3~4hq&WWYQjulr{U$pE zqW|1FF5e$h>ug-}`myHEt4Y(o53*J*bOx#xGncTVR{fvRlKHu3d#zP%kaeXP_+@7Z zG5HA?5-)2f>jHlW>C3;{hHa#XsX-x@i0$sbKiiRO*Oq^G5?!VnFm!O2@ABQlg(&#L z^N{-D-G;vNsu97vv}6#H{s=;@a?Cmu$@1lwV@~ctanp_r6}y_MC@hx%_Q-lq&noqM zFFq?A0Ll02Tfbr=YI(VzPZ_N9<2CL!2IFQ#iu1c}CWV*7TxvHza8q^iq3K?u=64(A5tw*#a{o=6 zU(j3eT4`&t^?QWlj;K?jdzR5p5W9$eMdK|VZO{t5mMisLE$qhS0Yhzy2f*_xb&6}d zK7-^|f))0L43vx86aA+ui#_U#cof`s4#Lr0@7v{q-(zxG{X7=-%TTc4%=L;Y&%nk< zG1CCKMJO|QvA&;aRbY5;3WKW84|xtY9Unt(x*mSuc!M+f9xNzl=ToABl;7pK0tnjq zkb?MH&Ezd^=G$tgAa*zE6usxNa}yzlB}~x<6PKN0yMwkZ*PEwnYMx{U;CsAon`DPh zds1Ah-NkW^QQM)cY}tT1r%0MR-UIm}zIwvR5vGHW zg0OuOuVt$YRLHf9H6Sml-W1=nb;^U?#Crv0N`PfmwLnwyc=C7Qj+;iJcOou}z2FA~ zN}ZKQeQ+fuzW?#&e&IDQ`05frjAK-749_R?yum zYEC=D!DLRm{DQM(p=hRq5ed`%dbM}S#1+-!RaDUQC9z=5(ltb_d}cXwOjA4BT!&hQ zVZL0a_ND|aI4@VYv}#{+0^}mQkcOsMmJ&y5E_oe4I-%y)D^=*}18IClog(B#r|aWC ztxnRo_oecKs*WLAeNz@x0f^tRA9_Ipx4To)6Gl)k5JbHj=a2iq;@htG?lYVGkA98l z&eEM%x3Hw%rioLhkj;~B+=VBlW~uQ0mQaYUUyZOo861MQHZ@Ou4mAR3SwIA8+Z4KTcy28B*RR9n|oYbajpa@8K&?!uxexHWBN?cXQ6%>vkxYn^fPql>_YjdJXJYlOjlP%Pr(g+=O7=3^1ZuOzhE>> z=I6b+*+N!GlZ#8N!qnmKj4@Io5B7c40yIOroXqJc#4w(jq>a*}v)J#@&zD1q?9v*# zp&ChohK)9{tG&~xE|dy23mc&u<*>D{OB1$`EV)$1U978HlaHq!a)%o?Gplnzudrl!-b_?-5`mJ7H%{%FL zK9Fj6Q@ebLt#CfxGxooqFiib#6YYiL@*cK{_=?W8P}5Gb@RY}nIYE}oBN-%QhY;2F zBtm$xywgo+txbz&{9UP;dCXb&Rrn2tD;M=nvM2TYYqOLSY630iaNZN7pd7g=kyO}@ z5RVUv?CqYsOPTIM#++xCl-QqlQ`i%^S^75)!;4ZAIXo4(6ddr5Tk4exHk05)qi%ae zzv*%gLDCj!X#CmcZyb?x(N})Al_S=oPlLQ2d%Z@ox+-p+j`y9yF)EZ@noUmVsWIWo z&@A-pePu%3hQ*^m0CtJWNEU0LU)go~ZTaf+QJtzE{eyMareZrhpXwK77Abj`oY2kp z#Fo|5e724v1_%1JbhkNL3ygg%o!JTgOZM^HgYd?!7RBHU+e2!;Iq^rxm|!@}*-mx> z&92!ywXc0)u#O$w?JSc=pXD(aam91&;0_#~<)bV2o|-e@Y5pZIJo^X$3F>^QQ-5qo z|FJ|e(cZzmV=fp;DL*-?`|TQ@eD)&F#kYz0`$B7p9mf5_3bd7(BQd7%kstALtZAi2 zO@VU$?B6)HEmZiUArZC7-2-U_&GQzS6k!%BAf4&Y`s_x8%^!tn-cin>?lN(WbQD@q z`ljhJsm3tW~ShTxcvy$BAr-5~WCk&n?185n5EghFYqUL-XDk)A^kl(~FVf z5<;xF4eXLx*NfI zIwB_|g&!<`Aa!9QViZRq5L8Xo$hMC79ehfVhAokR25mm;Pg&Cnq+JY>lfQQt^7(sL zR=G@pk|U-Lx#0Ua!FgOt800*121js;IJ!YW31Ry-e)ZgW*$oSA%=a!e z_3~kIiNwsMet0p03sH6`UJykb!sxF{EFr^r-K6 zZgU>)h3G>uxiHFm!DeyCyw)~g1qh&yfYDAh#xwQHa5`@$Kc)&S%K9oUi_T&yA?n>b>ae5Z?Op3^ z)`Zg6O>`dcW;ItsJ^yf93r^Tj#@cA=9g))U%qwk;}GfkE9lWW1#)5k{Kuq9(F@+H#y9~=!9>+)*hMi9!rUdp z3Ncd>?l9a^z{=14;fl(-BCw!(V?E))RkJfjBf#0gx7^_%N+ z1Y=eZ`>cNaIfE`{OExBUR~PQdC^IXg`}D=EGO7O0uXVj!bv~G`mO9|{IP^RV-$EcU zz0n~6Na&Zt>%)9@8>w20WnQOZ`J1So1SHRGP6>lG!^Mm1Jo?N`x?n3!c!%yg@_=Aw z!K0B}96V&b@u#{K{j0hu)D#-z8!N5|54BvYQPk?C)Pu6RWM;EOgkNefrj!CAzIS2t zaGI&uZA&ooM5c!D0I6R-W_w?dN2I1;!4p+)99~sQrdBmUGY^hZG{SVoYEbi-(U69H zPtRzKZAk-Ygh!@1uJqCh3lQXr<8)bTDO}Emk9eG80@uDMxzLapQ2l!;l>4YM^=c_-{XNpk_@hp0O4R|~C=(|H$ zaxHg1C2p#;H_hvH`P1sC!DrLb_hwKZKI4x(xaIAUYvW9Hhr~-Kov`sO=Lm0ApW^ydA*3M(I9Bo6u|3pReex-9wZ*+=T|>)ny;xSiQdLuZi4f7pTaoGN zn9|=68Bb&cqkcb7zf-9fayvBm>}KYab$Y)5DqJ^gvugLGGDJN$HN-mpCOvAS%kf6$ z_1^4iY5cx3=Q~j9TesA#%BiVIXpVf2!M?Qml;hx274=T0}q=3$a?fmza7%4#8rrU{m7ha76oT zcXz{JQ%K~fBJ?bQ0x)s5+|Yf)g05pIbWh`-R+!8{OrRQFOf~JLZ_$~&DC%5?=F(lj zMv{xYbYWg_fXI${K=zGxVpmw$P=A?y0pD)mxwC8Y4t{>Wy-{C#oF1z$<=AZhIduHm z+w;DSV3*Y5F*RW2+WO**U5)rH{e7Fj;j7mp{3t;gn$`ouElPtOGny}_83~hq!{^@! z840u*4c;XfJk^h|`Bc&L!ITx(IheI0lEtfc+MAauKbu{-otpGq%J-wJ!|x-1<5<2h zeBm~mt=xJi1#gx?pkdI>f8xmBPCYe@M6Aly6YEuYDCVaf&qLs`eQ*qT%co(^AoT&{Y>$G$wcH6e$czx5!=$@1QzKqJhaJCqF4_gZBnkysHmbSR8!p z1sN|cxNZXH(-mnz2hx!AX&dP;>rg)&yUBEY>aeEx*N$;Ktp)cWkMIikPNprbTFpw! zc^%_Vj;8*wIfP{H+Ok_%J_!qG=}HLfVyEmFpXm0y#_%lbz9E^JmI6M7OK*xlZVbU* z86C~wqt1Zah>Om*xU++WrkVHhc$PwdPY|VyGO2VS!-+!^MG{WxrqBISIQsNe)|L*bBeJI?E*2ksmT>P! z8G$Hv*7%NPdr|IzxSW8StwLS#@zdwbs7e=HcX1u&LlXWlfU$+ zoZlOTFUyMW|Kl2fHahr?h7<+27-iG)<5-*a4TFDQQ}SDA}kSiY@y$6t(PY9X`hnR$Oh zV)A}ftvTsw(aq$wGaPAf2bUw+$j8^3B(i;{irFcM#=;=iK^ZD9#r>{pQ!1MxLfYro z0Dx23V89qpF$1QGq^0Kv+@Az=nn{konw z)EQ_w!$?lf1FFN$6==NhD)8Sp)ozT5pdP~nq;hQd;~KCFVjmEy0z+_LX8!0Fbw6UA zM_8#zXk$7a9rc*>#Z26zSsSf#oVi(=$B4sY=+UhUE^Fp~O5Zu@hP32J z6Go7YEoKUHtY975K}JC#hQN-SLNaJp%XPagCtl!uBHw)r!@;4RH@piB+O;S05=slS zJoN46sBe%Z(VV{@FDP(Auqw1s~>{t&68)Uzpvcyu%aaEN5hj z07%jHsvh9UMiT8W^LE4s%P|wtZD;p*^u;&+KX6X-Ap@sfi3Kf;IfPST`|$~j)8}k^ zg}t#tLkhU$FM7p&Kf0gR{${-&4SKA(J2bdz=-K6m#j0_zC zWwJ!XCAA;xN2s;IZ+DQan#WE`%yo!ws@*ZU5T^iB(b~A8NiwtIFQGbGeb0=T@D{66 zj_)DMYE#^suN)JxG#YB^aYG{2!3$0CqcN;EA*Ml$XuuAJC9YD#iS6#2R=$!@;Y#^q!@MxGf6upitjaQ=IjBOVd%>zy(re5 z3dMTTGA9%`Z35B#^Sn!ask9ZL`T4m;*Jk2jp+4?CF@y|k#mh}Wu{%A! z@fpN7;zbuBp^QXA^!eD)O7%wnNLkOjh2^ZnNSuy{Lb=T&bP<%EC&KZmdErJWO>7TrMqjibwLSg`0UydXmu z|84iYGv!}{YpVqkCDtxIPV_Bgj zz1+KV`cYL?O1_bh@`clTOmAF|$l1w*g~z{)_{ZPOIIsqrkR)7RPsqht#%Qrlm1p|v zy>A(Q<7RQ@4wdtZx>bF{F$<=p%KPW+M9`$L$l)KqYYN2NpWy=ze9@4*j@W5QY#Dzy zE7MHzAYnXs1#o?R_CnP7>SQ4Gbd)2+Atx_i?W%@p%99l9C-duUZjJUMLk18^VXQEN zYs%5a^?S&|nU#lHZT3C_p8~#JoEv(j&@A>SdxbCj;js;X@x)M%DzkBkY;msc6CS1z z>TXb`TK~QHR4O$ADa8^_K!-HAEyUCto;c6>+vt0Qv4Cx2G&BKzyT4*^p%J31(dtA zs+;5Im4-@Xzxv(Uvh6T>0Gr(CYl;y0SylD$LU}nkXltilw#kp+3;w>pbwTs;A1>RQ zgUdzb@1JVgXL`RlQ_uLIGuEqg%brqQTocD`^e4SBwB9Fo_?}0{7=XsES`RV0tce^t zTLs~^wM*2))+B&~$Hxd?))lt#W{O2E(V_0x4>vnCn^F(J`Y0L7Qk~d= z@Kyh6+(8*;@{BH57ffbVPu}MVDaTFU=gVysOY&tJyhdMB`c%|J3iif3uQ;qr`_~|O zW325{JH68#H$N-G`jNDkH=WD=(mnIOo6fcHCwc`DDpe`R?#Nl`e^x0>OZVAiN*DX~ zb)NQ8{5@n8QxN5~o226!e6Omy9G{`R6aSz+bfo2Gme}6F^u#P;5T_y2Fgq6rn$}58 zmY8<^l9YEHE(A41Db<+GsSzf36O~CTQ7PBo@*a(>k7 zFU}MeM|>L{n9nEj9H=0RLUZ$&hQ>ZEt<$(iSV_^-jU5{zGQS@LR&CF zSp6jrBaan?rf2?o^7~<~N_30u*oOlCzvw zd+a+ST>rV((_$MPVs6hpyoazgqsNFcsLm%wf#gB47YFZH03R3aKy_(FGr#$4j)a@*6cNLKP9R9WoZ zMX@rmYT?rvBj_j766OII>`3^{5i#WH)9luXHizq%(l`@V$t2E=UhV@Ux>B8r7|77h z^|#ww;S30`M;T^{Sm3{%AZI6J;rA%8(s;y*eJ+nv>|?<&l>!a9%~JtsIrZ_$jY+E; zG4CXi;x8XLpDimid&#JNBMjXA8^`yQy4Z$L_8~bWhif=O`exz16i)cNQUbY#kGHy2 zfauQPt)t)FD#TZFjiO}NLL%A%=^`6Kc6EuD=W-mAoNXZHhTM4zZF)U5!2|sUeL1Tn z;l`gqGRrm!7~^JLe!;_@m*5Jb-EGx;48N+yV!0o{X>y93g?$?>VSU!b?Es7 zCzSdyr0XBb9DC$k$uBeraGP6WBa(PMP1|sAbFo@KD97odbb&o@I0`MOe8@RhGnvAF z?VDNl33KP`=H=%l{iye1J83K~o&6Jztzq{=$LQzAxS4XQ#*jdv3#+NhY(@*WIMaU7 zv1iXM4A61?a=UG74ocI9>h$~$d=)}c>QBNHBz*4%o{;XTHfP7i&?$ug_->(vATI9o z3##adjlgFXF7;|eZzl49V%;>GaP7*a*2Rj!W?Aw(qDEYe7*+k?Q0x2IT7yfmcEPM# zE(`Fb8pM>ggrvOQi=%y$lK|CT7&mmb9=7Um!t~THs}|KSxj94oSD-UOigm9SO8A6- z=UBwNbM&hSl#w4w4yQOH72sxlE@iG+xHx_-$oDTMhCj*!i#qPev79iaMIpZfVPjgl z0J2|8hDQ=ibBd?7I@CE>_NQ-(v)Zxt!KoqPWFE1@uYQk1Z$W@Sor(tVN4vjqeEubO z6FXjZ@QOxy^l3yoJ27}d2xoUvIyq87`?R+HM+-a)yU9Z0l{)VfhB^c_Vs_;{PWi$+&9gomZAFnqLdeg9>P~lWgH0~*GX3KPa$0yov$z~ z8~{uKSq0C;F(4}RO23X#(h0@-jl_8QHw2O6qYn08AK&_rs&kvSJd*h!-CYPgA?m2T=-i)YVw7KgAqsHaxHVr_tnp($Ec z!oRejqnReEsuw_OcZ?Ph2>EGawr}rUiFv5@uFeMtXt%YqTJ6KlXS*Ml09Kb({V@G# zp=LGIH%w|_gCsnQHU0AE3o`HD^>BxV)Yo6$a_Zkw^nOikb_}uS~~y#U!Mg zOGaM3dMly#)DL$;^m1=@MO9((3Mo+js>&k|E%j)0Q*Vmu0lOxwOQcgfIw1tvFeyTe zw&_qGO-@|^Un3?LeD{v;S|#MrIw*}V`=bN9+Q)U@1LzkxTtyD~{o#7Nf!Y~z>No!9XM3=MX2nod zk>UO)+v#EiE?7#6JErah_jzeuZ1m#GpAAZS*#rG`wtHux;%WK8mrw3B23r->IgFZp zeQ>5IGs@LAShyzAgL(}9);o9kn_i4RWb2Y=oDYpefW9vWQp zA4a?X*Ia&$$;}by_J4KDZR{o~^3$5#>3(g(=c${}ue3+<(>4E}hw22inx|3L1OFO( z_5Xo>tf@9bISN>4L8Mp6b1@qmy`Bx4F;(ep>CcNzO6a6r7R(nf{*0>i7>fzL#eAx1 zdCTOLobue*=YM*1Mu^Xe`)-Qw3$zpu8b3?$r2q`Ql;0>T1>BLPn~SbPmy4Fx2+rPb zC&f_WQu&aF9Vn;9Trx9KUH4U2nTE!&l>e3}l<{R~Z~?e;qjf~2_r%_cIv7-)gg6AC ziz~c$xW;ZXK`E=@rmriUI~qS#PY1>gGpkmL4u**|(1)oS4C($SHYC2H3tvvJKYr-y z8+hDF;M{^<(%dnNohf`FKlODa4V6Ceuv&UW{HnVB`q~_H6neTvQ&*i@p!evk9L59- z$nECgV`uXm4o1=e!l~qqIFY_d2kn5IOP^9MGE&1LLzT%lo$nDMHt$$x3|}Jl7x{lOAaA{YEW(`2`V7!;k1QhOUPq{#HCkH z4hdg^y-DMAcvn0@qXGz(x(z0x76GS+0Y@tCS76kPwc_qk1Vr{AlhDNe%a?7=;f_8% zqi<_3J)}9}v6fiz5))1@)Uy@axto(;5b6;)BVn)gJgjA>@X#SX@yo~(?V(!^X9xW^ z)yXk*)1qf5Z|5H33M%-mZ2*q)FS0H7v2%8H4bKU5BngU>;|?LNHBq121gb`S{^Pk2 z;6h^2Fv=A&JQ5;=d_bG$&VgU7MM4fCOSIJHc{}WqJ*=uAK#w^9bNtrz?MMF}@|%ZN zs7eprgaxql4*{NbNle-8iK*Po~Tx$mD_|Lu@Jhq>(Q`PR8WAO4#* z{JQx&H~F7HM6cnu|ImB>zh*pL`KRubgf?123s^TYPkVduP{JoX7lhN3NwT~w3FPnH zY~-j?*@r~ztoQ0rA!`ji460Nkdk-b?bVQ8Tg)%}JX_(sd?P-sS+J~XkyMFz0%F&$| zgyO`#radbI_-irXC2Qo+yE0@e5mg9&iiA(1gr7G18q=OBuH{f2mO?hpB%jYyMJpyO ziI4WkU3=Bfy_w~uQ0nfI2@PS=ABZWEcq+*7&&^934(w}LF$q1q4@3S7bQrh*k;#p5 z0a-T)jJ~_}QS{;gzY3ag=#G4pCxqQ5gQhSv1-F-aBMVUHY>rSQL_4L8^E_-IMrF6_ z@3LJe0OUvgKIQQ-5`-C)j}yMDpNz_+-EkK4D_F4XFdmi!C>=Nb$;))+^E7$uh4M#P z;)U;=dwgez>$bBqPxRy~J3gpa{TfLSpr9TQsrfoHCuj|C%b=$5J`nn1FZwAdK}j+) za0#cPF;ByEm%mI-%kD`4x#r}6A@FZV<(W1+0@}%`g76B4vYi*P;L{l3>{nH@Z1D$d zxE&vTxPM_;`z$QvjA9pQr)H|Ik?J^kA8~(6O2AiuLz=8O@g#T*daK^xoTpzxTp9?z znJOo|D#xRoe3&$OP-_UX6WI3R5vn1@%(gk8~yOhe>c{uQ%e^Rb8^>9Fr`d9DjdEzuhA<~Ix~QyFTEu>E4%RZmK^ z$GYF~zpvh%nLL!mTk7kg+jZY}(u-x#mBy>el}F zXZA*qR<$MN+)Qd!vU)q!WfT>$-1*3GwoO*udB_srwG~c_Tc70J;N@K#$hDe;e(de| zRQ3?3-fs3D)%#Y#!aOvYp7IdB;55IF1_w5C10X4bvSMla&vm+hXPKt zpbmO_dJ5cyZXS8|>BIrGj%sK~B{z?Cm7jwH&9Z&^fu{bK3T<_~_UUsP6#78QMTO~B zBBb{@ja%`j!gKehzs%x8>RJ!UmjWk>#qJae?USUcS|%PkTJL5U4r~Ca7xmzQ1Hd;Y zOMVNESx%uxf-A`Q8gII*LfyM{baOSrrOo)7&)4#Zvo5~Sl($gkr5l>-&J**5&C=7; zWcz&u-yScg!#@W6&?+S#m|3-9wOYz=j|@f>;_X&Hblj(avP5Tb@FbzRBU}A7#6^WJp>ix_ z3Jyyi9&nIR6c=72%v78_V0zak*Vk?b$a#h1jE9#FS?7m|tDb=E7Qg4#9dTOzDORe%Sc_h8QTX<_4jl~1EjVJ{+*_wn)Mj=t8!BWY1DTKvHb)*O z5--L&?CN;r_G{L}ZEQMro>HpdfGknuQ=MGwx{l)#KXcls@h;tIwK9x=e$fRXu$vF!NeR}af*n97&Cf99U92FE{fe@Nf zlom>;VkiO@N+^L)LJ}Yp1px_7LAr{9v;d)pjzUN%2?2r7B1MWwRT7#s6%c7EC?G28 zy4m-)U3;%}_BiMMan5htamW7e9ceJ;_r32o=X{=LK4}cS+}X(Ye#O&Lj;_ngj=>R) zw*f3!0}=bm3MqHee?h38JdH}8@1NMOoL?(*bFFu+EqOuT_7_O@;2X@zZIzl$upKHx zJu5aYzI5}CqdN&^p{a3?yu()|YTJ|Pwt_AK2fUCIB=L)oW$n$OgY3lFDFx*M3XZ&9 z3-8Mca@xJAVy;7VfdO8&E@Bbbqi23xQUdRbyxAG4^L=dBCnnFJMc5H>LZ%C+NOmbD zSvV^IOE(@!C@#vyo1gu}C+G>?5^O}(>F5HnR{jdh3_*sFv+NYq2d8w#<5~eDEGGm9 zm))ss8XVRqB!QBz3T-FsgeG}8MpP2o-Z1f}*P+H^y)UwR=oe@CrAuad(0doXzgBq2 znUC5X3BH+Rm_4cFz(^5R8L}wqmfxdz$(1|cv)*c~`EI}vb5?Xa`#!L9N19uV`I_%e zC(=Sp#xknTts|_g-z0OrNt~q&N@MgeVS_Q^FVbb{cvBRI1JjR}XZWFj;Lp#s?Z4`n z^YQpx`L1TK;=sOn4AKv&js<`-L`biWz!vOeB9n1Qmg4A)l~qc4dIvJV%H8D0lXA3# z?ssYQw@W6}r3((@v!1Bu?b2v-=XO+l&i;}$^yQg|^PgH~X3*01wVb1{1GHqx4U=VL zV12QJ@%m~N*2-6Fc|B!NsC*!VS+E#{*>jTfl8qo&zD91K?>Jn82oB?V*psGhs3*_e zo^$uQV{#4@ttFktJ}3gQqbl-3^)$p+y(TfaERD}cv*z=3eK7+P)?|>}zU#mcHDJRv zD=92zPdJ;VU^s$Fa&R})+Sg={CB<=tf~;p?k2G^&V|Y zuB_baO9~2gxA-g{JB~J7t3Xe6c7r?8ZKb>w73PUkSG7<55wr{GZokkOTLE-m(87tK z*sH4iMJ*=(Uj8@50pgFgKKbjR^EZG{t+V3K1=`U3ag`{X{buQ(E0iDt8GUjUejHl) zU067qc#wb^mv+Nkes5=w;G!!3*hKrrwmks z7V$^L^6lSu%m2VuIZn=f@CRDxw8EF|gJpa~8#efE@cBD#{pbf%#&jzyvb8Zn*LcLB zVYSS_ZHNs!d3uWXVPaFE0noMj&X)u>C~;;qi_Yl{nZJA8w^*CVQ3PDt!XIT;${3Hw9KJXB${g8+H2xZ}G?hbnmUw z+~-AS6;gl^k8;c`+HWqI7B7(x50Dk;M)QEg*b<7yD|6k_&q;1iSk2188X<}j+PLz7 zmGkh?Qo*jb-Hn!!dVu4M^@ST5A&@ah-{YlAsbcP)eFN-I#@Jl18%9GmxWNvBAy3&x zZ0=kgwwTK(_k8yCK%Ef(Eh@mikHQ+1zBThZ8y%c66UuT%t-))Qzc}$YFGBo?x|oZo zs}Ipi>x3hM-#AaM3Ndw;>b8>)YD=M#{E_^q^ikJgo@IVz(TvP7I0{VhzINt@o8k9S zoDx+D`Nil1%}yCOk<;zAfBXD5co{A2Z4=JVe%BpFrNS6$S@4G{{b$(20dfAWibF zz@pSOVEh99^$BBna{YBv7=EPNVUP48@?x^HZXLn?!{c9Yw^OspC{h@IH&6ZBXxC8| zZrI~PbgYCXx?-ky3pkFB8($E_Uaw^7-i17Q zHGyvSqSQ2gck9-oL=>y2h%Ar+FH{d*J%k{Ksp@=pd(^iPmYGxrOBcE4( z!_ViU68V%acABHk-1Qgk4uXP0Rgt3`ugHRhLbMjNG#nj< zbl;gpf>_79lhW3Nfc5#D=y5?Yxylw_s^kf|%*P(a-Ourod31_LQx2KTN(ZKd1J-j! z*UQO`Fo&MCD@T4*>^&rE#lLERa$yz7x8MgTWKI>60T4*7;L73ZX7`uCrDM%kN6{6u4w7t3Fz~74l5CQj4)B-sKIG8<7TVPELh#eSP8K|_p9ZIue~# z2)Acgp!mF=3GGxZ`A@t(N3^uvStl_08Q!H+@l}Rid7kFz9Qh03ITUg5OGG zFbf!Qk{nvHGg+0WES_Y6D^g`i5&4k%?J2_X-4epv7^dHNL90Ey<0u(eampyl{d%o( z{8eWiFH>{xMMmxUq-yHAjyw#5*oZzHY?o`c*t9*k=)iltkLAw#ZrRIcChVv?cCY1E zSVza$N>X6@`>CffHd%sQ*Ky)+dIZ?F1tgb<-`7P|bt>bD->*Q|PJLJDV|@CCoicA0 zevXVqtMvg-U1DtIwYisI)NzH7uOYn@foqp6?~Xoe#7-I+Y?p*yE;d@Z%nwvLqg)Rc zY|k%?vGA=F*p4R-8x?sELekTx)a`X;4pIr zE!Vhw(U0$dCMQW?^ZKuI24Or|R~>5NHlNb-=tM&38QynZ5-*1J>hi*_sDJ4D_sjoH zF$w$D2S#lD35H3kz6t)4eG|;GN_aPR^P6b{Y;*18h;}FOzkEqTk`S&EwfE2Ds85%& zwOLbpr1LY`s4_!5vNUv%9 zVCLf!;Bw!`2X8XqA9r(MKoK>qMlmu9sxm7++cfHmSCYl8tF9Zde>E?(%H+X@`MA0M zG{_T}h|??KhmPnNhJ4aqGqZ4%G7IWPcqel+s<}3*-F5a*yj7NxK49xMD6KY@Pn`BT zk1B{bT*XQj#3J9#7(u546`T|PoZSBneHqXg!+7@#@k>?NFkXWWd2QW?ups9TdOkjG z{)NS;(khYVuJ{c2>>i$molAc+l4LRGU{veMUoIA+nt6G&05pYk%Xw}BjVqAqAm)9Q zmmKY={r+&;BIjkLRfowB#S=)o?ql4V>#^UeZ^h>WhOjx(6 zJfjZ^EY#il`WG+`kT;EHo{{x})#YpTdCZ>3^7|J{iIbUME~W+9Z3h0SK-vHHPu#wn zxgBTZ{=Mb?r_Y-^)xo*P*#FpmL*Z)l<;x?*IU*`1nlqT7jm}DF)KkRzs z?X}zBsh}xJ(*0I?(0}_V9#Y-f=y7Mwwf$k{$gmR6oD-T0G})m(w{QV{E*Rzj1)&>U zzx8E@zM9ksC{fY0Lui<6WPX}bfNuLs?R2)s9|Z`@r5G1zLfB7z_!83FK2UO^O=SX3 zU-T0X^fCs1eOx6i{nZVS_UKHM+VSXSH-5m>G)~$=eL-5cSjeC>*shz+DRSkrXO-l{ z4Wp?B!y#Oo? zEry7KP+w7%%WPMLT`*2Ojp4pu7DQEta-lzHfqtx!tB1R0r+}QWqY%&)C|Q|j;O8)p z)TzDfM!Ei*pA-1`)6vq$A{WRKA+1mJ>a8me`<#cmSO~yq+f+U-=VawsLvm^`+P(3$HY97b922F zvfoXkAH!NtGlC!2@WB&vn0Xsm3$8@xWjd&LRCh)9Vs599t??ygsTj%d!V8#);213I z3Z(jEdc?l_!8`D~EPqUN5BtTBT2ahT?>PX)g-Vwm9r)EgLgotD_#`v7(A_YZR4wmB z(A^e5cu(x?=EGE#vcsu~l%J0XZiD!WC+u|}pvHxvshPC8`n<=w*Yv+~__?Y&m>1w5 zi3G2ce8p!NFHF^x5LACOHnt;N^p1cZH-YksQ-9%e_men21fl$SH*g%*Clp(+Z80&= z;{>;8=I?EInSM>e+?;|xNji=}uG|;Sp*AfbOn-!T4c|-Uy6?5Ya8`6!(V2bpr~;|P zl^AgJlF}*$iuFquXc-1+Hvv^v>=zLV)?d_(kiHnlY z3<&;6+H)v(#43l^)&0HVk9T$}JoVd8Z^h&k`v+EA9rC$0d;yw4X0;|oa8s8~Lpjz^ z!@$|idkUx;<8K#=PBd)~W2yE2^(EwrwK! zE%^QC=^M9xbPJXGOdi6yQGBXGy%!xf&E%7a#EHQ)cnU{;ehk~-^eM=N3n@4JVAVbe zQx2k*!+eKP{ofRSwq15=3!DipM(567|2vcY?`lyNr~O~9UPLz+8Axw_55Jhcu57n? z_g5BXFP=xaO;#0L++UU!4b#4lJpQfAn%2Qz;^ld@+|kF~lb=7s>cO7%sb}&hPMA+8 z0J(-LhmaMi?Y2s~u}fW=_f%+_XI$Ty6`q>OcLVZA(4LqKAoWfYWDP@oY!eFgZcR^c z^c=?*z+_HeD02=JjcBcJGIFIUw7wm?VI?^$o8vW+vFX6*)=rxH5#U;3ST%j=c#-Gq z^Jynji9i7Ye*FCPE5j>5L3n558TYCMp28+F_sh3fVMC-%lcHqrK#S3Fu(c7!UlGF$}>1+nD`hy>pyp z@c~G+K1YQ9c$;U17g0IAJ|!TtAGS_pr^BSP1G#&8Hq-xp`K@1N(?(r2(A`W@sG&5F z|NPfq_{#EE6WiGnrjZ({JDw7&gL;hYurh^Bmc3R=S^K|V{%?!P8c_eAg$F-={O7&g z<)H|MV}fvxq=hm3<5nzd0Joia8wE23nZ@|F>Sb*X{3+l28r1)M?eP26Estm(lTq4o zNcGusWro9P+7CCng&|`#f}7j>pZ+N&WXU})-T8CA`Rbn-Ttjp1AM>^UU7Y<-7py<7 z5L?3K|7a-N*a*st2a1aM8bDmXoDT`Aq8=qza3tUo3PYTPT(PJOmD3s3r&5Mm(5g_+QfVHuNc_cb35Wt76w z`ozghI0X5@4uKSY9tytGjT z{MN`-qa>m|!qP-EGN-u$T2x{}ao!m^Inij3%z?C!f-aUgAj>T;or&dKJ&wXl8j;hA zRE8eE*L=Ye4p_K_D!&BnPCoQtDG1_2jI7d%*k&zE6Gd4zEH5i z7XWkFnrXS58yl08S{z>6eY7!RcjZ$Bn_WiZ z&%gcS$ZXINegP!x_+VG&1*rWx+cW3bh4UY|$clb3O4ZbVGZfP$XKQTyv0f3tYiTJ? zQIg~2mF7{JES7ah53wv}tk$S3mEA4aU7x6t^%ASkTsi{>i^`GuV(ua;X(Ri zNw<8TI^EuPv;UulL8z%1u}bdCp=tdj0?PB29Y)!)EWU%Ct7K!mr$b;>ledd3m(CQK zZDvYKe3q9`3%N7Gv)T)3$<@rWhN;7r9T+vO3_p2Zh8jx#w}QmHZ6`zWgO}JYOLi}3 zW8-zK0K40R8Ix))3H7J6b|-0r=_J{Qr8~(A_XTT@kA)pzwE1PQhg3k2?&h9zrhxY^ z^VVzldfR%Jx-{fd+A|sh=%1#R0II_a%39wb_+#X@E0(&yaZ{amW6~hkEpO3ZkHd1= zNg+dVhqNWGr!>F=O9g`u=$hf5NILt34CJy4DSFuQ>-!~{WXn=xQDS-*t~f@iQ$Y7d zG93!!4=5;xmIkc&q;e>q)yeh>EbC3p6d(hEG`kl>{Kb-x=`EQgOR}SiJ^jJ5$m*BZ1 zX|97wsS@Fj^;BnWH0E>-2IKwqdW;1uT}xD!{Arb*3D<~iZn^9>u!D$lmp+qv;^ zKl@jwcs}v47w&WHP1ie*q>SVyZW>V~(OlD3jguW0f_^D(?nwT}RnP?^a+ z?>C9TJUkcZjXxQ1S;5Uq|6nzvg`Oy9M4fsdJv@?oS1TWPGZQGkOpaNs1OeRhRJr>b z1h`PX9>xHo=Qwsrq$VoueC8|flYkpH_U!EZSR@G^+heE}p-n6M9Gi=8ZKA53U6ZQ4 zC*_Pj=eG$RQXuo#uQ__W1K6V)S(iXvCErQ*{gu>LZPCBVq5nOAU}HPpF4Ma9qLNAf zt@DFK!S7!M(E7r8KF0e8zV>FfJ@Ot?!LuK!Qm&O>-LAdEm6i#rq4=ERg|KF-Qx(l zrMonQ&{T?dF3nrHeP_^uKAOqsLTr56#A&Nc8?OYFz4GPOdzIoX!P+x2d#RQObg5-e zp=3qrFmms7N&`RxsBBjM{(KFvlZN$FZ zDrLy>PEMAE<=XO3k2EGWzP${N%llfAefo@=!sF+8+*L$W@WkN8(^5(|xHx3{#&?+= z)Hi4Gc8u|RIS-SE*xQ106zhRAis2gNpJ?373b+bpUNl79zcoU`t9q#E)1y$@Q?wj^ z$-Jkt|5`h9sP|zFQZsgLG*-a7-!OS3Lrg&eygpig5wL*`7Ia)@O52_U)y{2oNfM@O8&cNrMgd z5>!{;;6QX3p@)3q#toC#F0*-|G;8*WZn1RHmd6~gCf!*a!=S60y6~i8VWF4FQ4Ud> z*syD^IeBgh#~va;Vd1?)i&pd-($dQxXQ&sxCi6VA)&?ab@JCi>Zm~vBMIoQa`oFdT zN(4J(1?+ydvYXZ)a0GW}sMvdn<>f-P!Ltw0#b0(O<(9?s3+@!*awS4$O}Exz8Pc&< z^5E+(+)7ki-PaXn^QKT2&q|;b&X=WUwBsFtS+$JV)&wmRuXW@_U5NPAr~k)34ayoJ zC`xe!x1lnIXQP~LY*m~<8EVs(Zbw%PN;fr#G9F7;RI6XU1brEEc74e+p%l6(L$?-s$0H0O%Os{ceN<|yxBQFYvCki z`*had&ZW#4D<#C;oJ|GnNlx<5KBl|QS8Mff#`i~qX4^n2iqi@F%?HdlGY3UM3=wAm z|Bl&s-ClDcI3L`N1cWkpl+5H0yd6H`cvPAIDR((y+QwBS(p(xwp0Cy`d8gBV&Z{g6 zVfHq5!+Vh{bPTYs{$*Hq45~&kfRjQXNN?;ES9Ke2$;Lw@QCer)Kf}`qgaSGT-#r=b z>!x0tEh?2%=>=VnYYmquf5e__W*qo-R(der3?DC74r}tqA(7ttZgOgDkMVqwksp)y zKYzIM5^bU9#?v5j;HF`t8C|g)GLJgiTP>MfLTv2fe&h@Quj*Z8X*?yL$ce&#Ggm3+ zv$_{;fTZ%$pj4qy2up6sHBF1pt_>Dg-*Vw?XpA+Z4>mP_;4DBlUg4^C!i-)QpaBv0 zr1HGe&wxaOZ@n%QxmYA|IWFlUm^21P3Vxaz^iim~JTBaE%BsoiqjAZnVOK@Yhn2C2 znob3!GIFY$lr7?m+9+J(qTnR4E>cYkcAF+k)T!L}!L5{fZYNvPc@t(1k`2MuO{%IT z(ofvPv}ccq*klku-7njC7F;vzI6K<8i^Fp0dT!0Ymu|*503#P-*VA_j5mIwqrHb1N zz4al!`1a&94U5GC_{~R+5oAyfEjqYdR5;nTiX^fmQoefVl3y}Uofc;ajAnS(Xv(&> z&FGiv`a$)D;SBBH*$#B}5mT;RMMU58>K5&VYPYheZqGvEx9y&^QR z$#k&zqt+YRPy=Pu)Ef&CRQo`%=jwe0M)haVdXJ!VJBe1bU1;zG*Qh)VBVtpL5PTk< zRWo8qY)vF^R`d`QMI}9}$0dxNWO4~DYQcIzAvQpc9@~q9lE1SphFHa&um9BAS&adz z1Dtru6<^nt_@=%=y-`NuHym4T{Q>b$9&y9|=%wuKE zpJLyBH1XqdK)WX!bj#8YF$mAQUh!%^+T|- zaxmX=s>|+owxKPY40zq9&=dG^({j%3ns7HO?X#!))Kzd63MoB3jrjTQQ2dPLZ5xDz zpbL7zoQIV`HCV(Q(Z1u1;SIBRsyshq*>lzA`xS%p>+|(&?k4ois#px(oxw$)*|7tN z0x<`d>}p^-l2sPciP$9%I5-K${5Yg-X6|J4x357CaLah3(k$g6of`t=mP9M`YD^M* zl!}=L2#Bl$%&%<}8Y2Mf&bGJQJ>Qm_k4n?5M5X0w$kMWA4;Oi6wdRgg16L@%exRk+B z3L!L_A|ltSSpaB(HSSa0=C+8-Wo8AT`ql zvYZ@gtVm;yT9DvJK}-M6Mh#R94jK>UeK8nAxW(dHAI2fRRb8=fd-|}@{&zM%#R+VM zIpbUXXX^UI!W7Spe}iElU~Kx({*dU6^24$?Dw34t5aK_HqIInr(l!sP}wy;m?jhJfn9k!}V+w#hTLtKXv??HFV z6*~9{cM;{s?IkWyCBp5I0-ORNpR#jX4Omw9gDR-1Bo!IcmKy&4AMP*p!Gf9-3MGPR|2|6@;swL`gTk=i5x&Rx7hkQ=+}Zj1XVs%qyMfe#zqaPt0%Dc zM!{pI);omAZQ!K%xsj#mm=Bt!FBJ^0H5_Y^`g@M?4;tmaTt!+H01`Lq@yVk?#tVCa zF5&OkB~_M??{)I-c>jU7v_0F6dU!1(W$$)yLIpUuhq*omt+mkcq_o?HRBOCmy=r9I z)_x)`+}CRNcu`2Z@D2FLaK7&DA{UoimF}W#{!#Y_1^GVTotkhZ36bQU5ADiJH>kRq z8}bOay$DhmtozJN`Cj5sF?VmE2*-w5KJ)uzF39{wL=B5u|3fUlA?zk7z|IAv{%%QE z^J%c1r>9pfMC6H$UJ26J)w9ac|=RJsLd;h);# zRv}z2nOLVN+mkdnoNL}YiDg?d-VWfJfQk3EE$zg?giL>?WhRK`3Zqejar^lCH1=tj2aS+=5mEPVvc1|@X=ZUQ^6sY-BC&!cU`NR+@;SWj!e_4+j;5mA!;^IN*{2GyK^=sM zKPl9tIIkh#Jp_YB0kP8>UM{-^B7$S+FMrS&k+&hwl!uBq!_&pHA>f++l*_<9rO7 z3$LfdcwRDwz=9iIohti~b-_+Wj(Q$7MnEZY$k7j4o9|412zhFA{pTm&_%3z>c8o`e z{QO#WfH`n7KOG;rs}gY{)Hz+wLFpoeEOsy(6I}~?qKCBR97A0DlH}r^*PA{2TiG*q zy2cX7yU5+#HAj#?vYa!dj5sm%RZ^%;GQ$BCiw z?#1LTapBmZrOQ|*;wkxP+C;V06~-;Bz%jvuJZ}J#MvyFMG|s|Y%+IO!mTf`m5|C^8 z!T10)#bO9*!F#XkGM*{h*J6^U)jdjkUxr>cyEUPx`i9&X(0+YZoWZAc9QG&p1I7j zL%F^z@#tv=q)Nn^FexiM!}{^BTfEs+fC#*sZY#k3va`C~#WHU^`O}T6=nKqIDN4$NTzX)hpg}sm1#3)wfdhs-94U;F&^{})|tchx-{B+htH5J>NgM*;=IPMDA9;ag< zx{zHJ8%IVXHgPhD-o2tO+UoEGM3d^Ht;fKm_@_?VaOUqZ;NqbIBT0 zNgC|ZYrnIN*Xh5^EY4%3aAN~C)d{r1(NLCK&N>?P%2+X5+H|NO7Z(70rQ(Hm0?0wS$&&4OMrpZ*HbB?C0|H{8mJ1_EwJd zP5hDP7^TaG{+}@*^IJfB#WeKpm%e;PElf{qyevBO8osPldgBt|(nmx2h!NEq5$)UR zOQJye;4-?#)PAk^>m_5WcEp6}P1C`(qfb$&p3GWZqUzqXi$xPy556gOaqQM&(7P)5 zgj>`Fy4sggf!sC1*T(MINA@brV%u*jguJ}7>P0>^`jbbDVPSwHf>*7O>2l}fjO$jg$5Z`(%!<~6-GoMoIgE^7VK{&Ay`G&CGd8|*K zrX+18Hss6NDI1gpQ4H-9FL4CGCEl+1%!W=$vx~4M)gFAUOVETP6*+;)R=rO3kOEpR?ZOvO@Ty)3bKA}%Y)-M`n~b}@LK=3%}f{?-2;ai)GX ziIi))KOp|1yaF5T1Z%3@LGO?*91jilk|T}0F%EVJ?QgYWwWW@&wu=tH6r~fBiFs&e zR0qF`oM?fleS758YX2}j;OIc{!;1*Q`c%DW@W@(3PQ9f?@jc@Y)i+GZQOn*DNs7GNz>7yAYAG6rC>`2e-4E7I}dy z$ND9fs`b~~$i9i0dvJi?gM#8b{(4^6BYy+EOt~HJmQQsW#Bykr@5y)4262&Y_zW@S zj-ec9OU2p+z>UErmR*9qkv9dgdFlB5B0rpSk*z&nBT%m+Y0y&O?o6f-8Ua~4^lT+K zK7;LvXh9xLOd2uq)YB!0I+ppw)1*!tJkYT{#+kEeHGvVZ9F{Y4STRmRzfhBxlQqw6z_>+$yk)3wq49y)2+md~AnKD#By zKuHBADH!qFrmQqv6K;uWe99SSmYJ`!B>tk%IqCFBl23%^C{=4>57HLN`r*^MwU$Gc zU@euQvuF5k}%>dp*P=H|(YSHx9VG1NN#3@84FIexeQ3V6QLnmg?m z#ZUp96w+(-pG~VqSU`-OwSK9whCBbMVARm% zk;lWirGuBJCleQKucM99bWlzQ;L;z=e9hR4W(muJj(+^k6?k`-gkZ1CT*Z4PT`r#d zO6~hkPlhv^3N4H+#?xp0`=8&l^2iHJ(&{`_`b^w^%7n?2W5Qh8Ikx^5>cIPMg@atL zw8E{a9*ohn69TRq$K;^AWZ&BO&y8qbPP{qx>Mu;fA8~!NCW%UEkwM~*G*)bgyApy4UQg_t^F!2?f=An1t|^CvT%1{=cOv(VDZppPQckaaUT zAt$X3+tb`~E}!?Op02uzja{UXPULHixhpFiO4CVdq&&+?Zj6epC}f#FWQ|g5&Uj*W zt%i(h11b#!OUgOZAqAIAG_U^7#v0gEu_=7d|LEJ%csg^kG9xr(4TE(|fMofXS38r} z2~&dK#24Ks=7}foP6RIJon}piE|e-i>{8FDkX)nxsJ8jIo;KQbgJ0eWSsTgA|4n!2 zT?=%CQX3aPIAQp_^Vpx}h78U1d}{^P`Z8CbD3$^Go3}Y;qyt>BOgx=DMO75|X64`L zKLuS&S8-?ElP%q2mk>Hxvb?a4HT{qAB;=2!Px1DlV~4B;%N6S63T(ex`GXeE?P~~C zm}{cw9mP`f{A${&x(XAK9&u4@l*B#O)1q!W%#+i~d3V}&!ok-JV-Fl(?lQ-HA@42}Qw#`|a7TU8F9s4ilOfaCQa3y2 z@cx5x=$^3N&18x8C#f$NpI!^R(){l?{(lOIB3dmF_>VHH={{Fy!mBaYH?_YmnU&2> z?a=1Nef%F}*1?nbueX2PVEzNcGh%kCmEKZ$rE8+nBt$a5Y;wCw`f`R(P_J3(mdkbJ zv*4aXODWm%(QD8B|_%6kbzt7Z%(9S|YunYY>dasXjHAo+9T`PL)+ng?~7; zW4achL00n5MxJUguH|HW_^mJ1v&j|ac=LfT(f+mwpTa|V6LPCmD;Bv%}h0mCMsK~pqj1C{4 zYnej8n)foDC!ZHtG^_hCV_RP2J|Z~ohd#Q*e8{sebHsYA?uEDTXVFQM%F!l z)O>BDYfJv^{cbtnoTQ+p0adTe4I6>=2+X;ihlD>z zoE`RLdken- zm+i$0Pna{BC;?M59}^syR*nofynii@WGn+@^?v2coC004y?W{gDd+=0jO*%Eh=RmE z^<}9X`pQ?6v~>S&-}}QdUKeRj5@Zvc3-9~jTkn@tn`FsaPn4Xmn4iqM@mcZeL1cXY z#NnB8r37cIfwl#GxSibNd{xl7OCd!&f8NG>iK;wALnCW2xx2&vWbY_HG9fp+gV9>FhjWOT}p{2+%$1{O@?-S+b9Usl|uidy-9NI5bm( z_dW`gH>lnUxn3druJURi$zXdue#iL{SAoxEC%3KEQjP+o`OPw;HB+`ExHGJR=kUZ! z386S90F`Q9WkHAFI*n#nB=5)=2vnQ(R zO{!n8rZZoDyE5BYCJ)Rg)8KZGPmW^=wQM;89Cr^dzvofmEbmnKTeP>SuBD$bY0IML zZ#NCR^i)sPk;FSmR5B=puCpolr5YWc7u=pz`b$tb{I$>Kgro7|T2vg-(hk*9R1{H< zx#|V`=(mM9SxbNRmplGP_T4%Ft4FOIqcsX-H-+C``7bxgj@)6grq)NRngXK&jfgwf zax7nM_Ee6o06wH=5v>dTn?#54-GqxnBi?UvZ!Z9IE%psPuudRam%FV)uD!gMIQ?xB z!bbMF@6e}c&wQI;6GXOwmokAwT=SVaqFf)VEECG~Vold=*cN8}M4q^|lRm1O-&kEIe(WcDes_+F?mdyb<_`?E12J;s)|l zJnf@;`F92x25k~T&4L^&l5CX#+uxsgdB$X;?p)=D#`(1D84PZlLTLWtE8H3O@4o)n z{x9RP-xK6G)O83o!~q3_ToC}g*Nxw4=V$C|re2BIhigZcLWa<&wknPO^q35uW3Jp* zrmQ2B3lmGhF|IF5qp5%v;1$!(;4di~%@<|Cw$33-3+x-^Dou(=)?^UrMYJF6Whuh8 z79aAsSySWgI>}G6N<}~O?5gDf=yYRbaxC|U(scgBV0}~(VSJ9MwMg=lR#fdx4Nq&T zr#0Sm#Yw+Kc{_)>6e!Gms%bGPFVAQeQgY)k$84pBXYo{1Ra~da%v$jU0%0zAi0D`Q zOEN4wZyC!N1opBx*EE=hhpIlgyK;k*dEb_hq1Gi+G}OV{@HrzSV$aZ`QHOnzD!^f^ z1|07Up8M-QE(oj;&itVHyyxc^2HIeb8!DCZyqbRHtLfU2HIBk3^0x7M_#=b|T)kAe za&X*IB5yrff7Sr90ce<5tkZo%TkRhl(ywNlD}4#_h1U*>Hd@%HPTp@!cw5vzsu^J;eS1M;kxzmjULr%iRLf1}I zy%sjFU5L(JTgbOa<^QI1Mk6fktS*RUSyb7QC*}_#R8F}FgKrV*rK|5%?r+MKZ#~wZ zqJxWO1_a-(>^4e&4{YGkC|v1W&i)t*hpxzr22!xi-1&vgr! z$@h;5dJeC0bg2@Mmc|huN;O(_r;?2y#pOjG4ZY3$>mC2nTxTq1V%jm1lHWL)9yAO9 zf2k~#YtMvqA2Mn|e4`6Qf8L#$1uivjEc^&4ej+af>|+;igQ1{Lj>>%y7J{ODi~!B%MYy{l=y6r7za&lXFEu z_H`tbd>CuhsZf0XejuUfHs$VNU$?q1OMp*S3KVLy8zRIcCdbZaE_rn+8A&MDefaU- zHIqV^WsdN?GsguT&**CqB3;PYR$i!k6Fmlq2Xb`zTuf>JBbzXv;inky6&n2bjD7l zOv#-%&|?i1Bu{6bn^+C=y6|wkw8j+>I@uI53Z%38fyIbd-b! zM_t%(hUpRJvgN$2c4iA`Imf8*^xxSu^Sx==JyXxxR(JGm1qQ{LqAGp-PrD9$_ENgM zR%L5f15VozflOC@a}_f;;PN#1bT|D$0p3v%(H5AkG?k&7TP2OHI=^;y&GnCgBBg7W zaz7hHpgF?f{jFDt*p)rfU(Vpp@b4WsMjY`heL7_5jX&R`O!`7IEGq{%IhLQ0Atxrp z2bX&K7=PY|GS9x%e0^1jhXfjHbw>o$zP$C01;SxJcSH|cw&1|$dRxT>u#+Q>4NWr10irenFPa|=O&0B0S3k3CVRoy~+4|TRn+tBV^lS$Pv z7y;r@I|*nvs_qhW^-XpV`eMPMw^@Q{RO5!r_2C!lhctX%Qxc0oPR=?8UriFnU=dCA;KS2FE^7OS};XdW+V2zPT-`EoMyR)$ z@)?uw?=RAZ!nQZ}<&LmS4i=WUdOmwOhhwKE><((M+(ub!nWJf45%Mb$>w`CB9KF~t znwz%OZDI#_WSbL|&V*VujJ7pEAS_+Dnm2Kf6g83}W0e(NKMU{QJ$EPDn#_PW5yEQ` z7G?JtVq&hr`_+G~GTK7=%2!DI6SO7x=IGJLEv(iHd)cqW0kF6=o{$Zy?=e_%n(ltd zU5~X%8kU$F74W_beB$PZM8(_pS95bhxUF&9pvuWCtrVhGmgZLz*J z-e?x;-ZKkoQB89R=)SqQrq5_-!t^#YoALH*9(jzA9olh>i*0Scc6_^&~ z!hdJ;o=}l{p zvus?Dl}ui-RKAYghllh~@KePwAn|y_oDez$fSoIru-VBT+7>maK#?0vy|V_~S`*~t zDvErkZ&dh~McM4Ev)n6sp1mfIRc2egSzS+XSQ)#)wH(#BZFu@qH`n#xqOba){xj-p zV{kPSaCG4xe}?6%?&SlSI!73M^+|i9;Y_A_o|1>`a=Qj+CdoGi_RQ9*|NFz zwPO~Nl;H;qD0AlMfXH@#RL1|9-vLtcao1u5?_L}(?WPO(4YSeXD)6jECp?iUKl}WwxU6%RE zgJ1|^)pIB<<%Y#Et=Dm#wMx*c6(lydfTob>4J6Yx%rcJ{?ARaRI2oueUH&2zr@!H^ zA|6s#nf7ff;UHzyU!rlG(2l7;o+qfMCh-DyntIvMWbXE|7)sQt=8I8|sZT(eahb8? znyuZ*maN>P7(B;8q=1yPi;Is9?4If{-_=LPt38)T_0+AjBegNq^S0r_Swcd9F34pu ztxJBE)!gxdLYG*~LAUM0MnI<3CoDseI>#<9x9R&IT! z0bCg!Pu_d1HPezb_TI^6qZXmB%AMIeI*W)9 zN>D;Wn(iiM_xgZ)P90|uOSYWsC`XfOPI3z*wJkb2cJ+#jpHe^>R6KY@IB^ho)|nFzXj{1rtBiRE;&x17a24(X0Epu$O7ox;&*IEt=iCDY~GT z=Mp=Rd)x|VmtsvRRo`m*iiiW<)wxqGdEjA?TaTExiu~2i;~vaclX^Fx?!YAhz#2wE z_?n9UcLJnQ#LEj7t$FbY=4E5TaQ4*39O*3$x_&SC#BKBeX_>khJBl+D&y@vAJShZS zI!0Fin#@jE;C!ur*<6^=LbQ&_SK!n(s5x3AuO^OgYjxALXMYk%6o?2McgNlk*?8BjchP!HJFjUn3$tMdR*>5C>FmtR=@OaSb zfL+C0ad3jDyXQca+qDhBXY*OLQFGGhE`>?AIwz$GA91G&XG~*hnMV1$pb1`{5YC{K~Oe>Odd2}7(c?z)_b?3MoE4Y$+4YDT_zq`GK5?}{) z$aK6EHrlBE<9ye%wZ z%C$5027c%T91H$+DQb* zc%O*8eD567^KM8Z?Jyn^Q~l@zCyAi`8^?vIU`zdhO6q*+X|(ZlVH!0$ptL&hf3f%8 zaZN5;zxb0%2*m^fgq~1CKm;kGh=dS&3%w{+Py|t610o89-VqRxq8NHdsv@9cmeaYj~ zjm!4{n|S?OvtJpxcYO}32rGW-;`EtRvYod&&&~6kLNSXrpStB?ZqCZVU6fSOvKmK2 zJ*+%m8ED&vT%YowsZCe7%Jmm@dEvnHMIc7VpYuFLfSG39Lb2S!B0 z+^$Zqx(FQe-H_Ago+RgZbw^CZCOD7qxY$cMxug*JijAnrj%{mIyrT{RQ^dwE(0JA4 zXa&))i@+%4TJF7ICY!-IYWa`fnw&fqv|Hr%DX#Q`l9SkZLpeu5)B2^-LOt_i2Ag&{ zV*cG+wUT~a)rnPmTre9a7wWUsNu6V%0mk71l-8DWy}>@E>N3mQ{;1&xUe9>b=>x*@ zC$3(5ql-VX*cvrqeb21DAOFzG7Ag#Mw7f^&$|{dO$NwB_;O&DD zXF|>2dpl4Xm_DP=B^f0YRT4`TN|Yb3lnE<1{8o^{qrSVw*?9Q*lj~J(Z<;9->pBfT z<@kA@5w^-ikCo?}31=k-dnVh{KarpR*u$0PnwZ#On22K^NJ;12vMggl`Vrz>+j05y z3Uwc*A%)qs1gYs>^ur6EY=0K;I0?B;W*R732WxmSJv=!1Hkl}mKwsz%P|{fm4^Q~M z(K=L+$2Wm$EVX={E_3+VktMJTIXc1cnb6fDk2hl*=YWvtL>n(QL(9@h4t4*7${AB~ zkqffkRwge5PUa|yV(hY{PX-kDd^*BjutKzLRQaKs#U?DB(hIF?OFq2P5EdiPflZLq zv3y!3tQP}KSw1HA+@WXL)SO=npWVN4uyiI`;ljOL^CxT{#fSmnEJrf6h?498tU)K|+530{@E2a+X<_0|8 z$wsXi-zT%-$&?Jb!Mk^yuaKbpz5t!NmdH#$`8m9w%4$`O=cvrd=4{2ghUX@TIe(F{ z3^fFQBFL*-$2=}%fxKW};4dEuNttbI^|Golc{1F1BsC`DMvGHoAaT3r8G+Mqu=Ppw zx&DKr?av&!1ju7@hZo*nJ?~?9n(NEK!I~krF>n#8OcQ(KXIhTUTOd9djar5v%@@@2rp=;n1{*}lmkl2hjD zqR`aGwGEHv+aG0lvbChqmPMf@Yx?gF43;$68qR=-T=$)Jv=0s{;1U!#xnSHDYjHiz zCzbBbS+XSdJDb~LAHokd`mhC(DGfSyH>*`#Ka=&S*Ev&Ew2eg)UB_YNM^_{*A3bb1 zdj4GS5A1dss#CFI%>Ih#H}BeDzsQq>3_XXe zn$&%I6@qKNE|1qScbJ61Y>j6{BCEs}Dw!)`*%8mM(GZxSd3cGwlIsvayr$Yqm` za}J%elh{p9Ux23vpW! zPJCvu-CbJ~F*LzfQpUC|=Xnp7H13g94r1j>qU;p~jti(R!LsVwBs@R+TS*y2D;~Wh zw`x6gi`qLuGqlfT!GK3f)*Q5NDC^bK#yIU)q%+;<$!|DuKXvHUtCZERwkR{RqZ=!4 z#PEFTx0xnebvT_dkttd`F0P{*G4Arh(y$DppPz5T^fvW|DAyHx=Yv-r`nWzKexD2xHFj zy-obx%5BDgM9YOIC+^OgTgT_Fc zODC(XNJYy|Wu<&-K$CNfSeUiV)8lSMPBM{ubiS{$;N5c@@Gk4{_Wg`Qgw!vY)mue& z2ZMu8>vLVMzHzK;vPw_wt^B;Bqs??^?d9Tavu}4birja@$3;EdyL_6yd7ML|)f0G? z-K(+|4V%jrugaA_{c9hcPIrlwtuY|prWjDH;)qpV-y^TfDUa8+0F?bcx?3#U?|Ba& z*av03y5}l;Z`UIZICY@Wz$%ITE(gmDv?y%zPYZY79K-)%#LYhj0F4-i!IZLG=Jcbs*n~fVx9b<=%!&hs~8sqS<3crB6qJFt2-v?P! zQ|Eck)eQ!AXBjFdi!TKZE6Q&SCZ)Cq)Dqu(Tues(w0_K!S^WO;{7H0)dF~be1*zG# za^rI;T8&b^8usNa0FX@nx#S5EihgB=P!ik>O**%`HDC52hdWAU-e4l+Hr|rfDN?xrGzNreH%1j|dYVBGeVIdW_{8V?U>;pmYyiNVF z@g_KfE$Fey;@!bJ7MGWq93-7iR6U=PCb6lXZK=yMbxRNFR#moS8?8RhnYl0=KAyQ( z6y%bw!=B!t^FegYE}sGy(YxJI|DjYsIvPbRlPIC_Gr@e4nPV}5<>p;ERh6w-pSy(L zvl#lGQTb+ZJJYy9{`}l=iv9(gQHSSorwkxck?f_O=~;^=doEsf;13!VS|QF7r9_zRlJSB6*5BI2bT!Z? z;ohXhPz7dN!nieYcBrGmsBZjV9_dRG-~6SJf7xT)aOInSTZ#TZU?rM=DDF=v&0pxJ zzhb5~WXJQzKi@IB&xEt*?4LNh=XP!RZFnEyzbP7VJtyEc3;KLztu@c_u=P@vnzIKR zZr<(lf5AU={$GyrR8XG)XFJ&JO&a`e^?r9&91Z`QfhehB1>HONc9lyo; zE^+AebMT<*uCDz>aCYIhPA}ssy#LF#W`QFAQ(G^u)bI;bk)zy;R=s_CiuTw4oWtZ( znRxYIz`Ye`?n|^{_v>9!XO&NNj@4aHKAuzJ+1HufSeVkbxn%|Q61+4x8#D2~kC=8Gea5tJSI*q=>60Ihy+axJvw*$>5cq|SE)+q+1s(p7X zHyrQjF5S~Qc6TzcFHyBV$Fi|`S55ai6Kf!FuE~fnWBF48CREdD{M(huxU$Qyd!EEj zS_wN$hEcf>%BT5zwmD?H2}2Ppb*y?%{AuyY)KT~sz_fpPanx2`AcxCHf>Y8r&cnSV zKi%h*XOT^2k^S@LD;G`bODY-SB#YU%>Ny zo!v&!nSbOo`oBN-);dIZrC|^HbX!uCVf+h-bj}P1Debd{ng1>Ahu$W)=E99P|1Ei> zkzr+HHqX11O>66J+xg6LD|g5Aw7a_G8Gbf*_k;gZ)MAGJ+&`RR{eb^@c=C@}|H0EU zpRS$l)3}ZOcJ<%U{}XhO##Xv6GQEkvX$%R^e*FI0uO2`S1%N?d7z6?XF<$`l1wsRO zMJ?B{%}*$Ezlg#H95uaj(M7?R^lKJCFpGdR@r&Hirf47Qx|F_@(9zSqX z%r~J+8u4dv_<#8IkG#kKROBCt|9stlGLiky`~Cl3$8l5D_g}dCUqv`>{s+(SA5|9{ z3C<1vivqvb2$w^S0r&hoDu&%R<~+LW%+TC(ddxg6cIn<;L7ByMSddpg9fr3Xh22}N=G9@>7{LxK1ozUqfFQ&T2kSfOz?VO!)vS@R_oQ?@GHIP zWRy&x?tyPY#FY{$s~#1VQ zf4|ItYq6RxBplEZ0B~aG4Y*##r+|#17&Pu%eMwhd{Oe&!ZL0OwHso>wE1sjFg8XO; zW<4Lc#cV&t2@i)p3flZ+#PeGxYpJLszuk7e_(PNI7cY43gw9JVKd zfAE_e%|vLQK6+7PXp*sE0B6UFKl}Ne$u1twYTWjG(A(d>PdI>(13vIA{P2Lx`r_r9 z`hDXY4>NEO6}>5pLFJtryB{z9&%TB{V0jy zzHs`nLPGg#){hs1yDh7JKKY5!jbLwpCRF0{K{Xa~yrgb-uKv|SF5Kh@G2*t851;#l zLMA!s-cnHM4cpQ15~ien{rQWQ%dczRB+BIe9C?y6B6i2a3UNNqAmmxV`H<+0=bf@Mm4?=$;nufQ`+mXQI) zFt!fSpZg!TVn^xT5$;QDoFA-sV`*$d1MXFB2FhURxP)Io=Yygi)9AQEQx-K3IGkN< z-NQ9?q7G2N%$<{Bw()&dPxIiIU^TY(mPoyY)2ss8qe*<1c5|o{UloLi%nww$B!+fT z99p0>&e0e&ba0L3zO-uu_{96ztMLa0;Pxp08U48P;naI)qN8IBBpVW6RL89HMRR-* zC(#R*ZYc}wveA(uBq>(@$x1EJ{#MdC=qZr6vz^kZ`CEZ+|1mL*(;=b zyugmzpkmog*@G0R_%@v@+5_1xECb&@;CrGxMOYPZQVK_Uxw+hI-&ZXYz)xg@p(xz* zNO&@ft72!t(VVzP!4?4Y|>Crrxy6jAm zz-yWapY!PR86W!3&8=<+$r1Vcg**i78JV{XzgO1hm@>D4HnUY|IF_@&4Z)F`ZbH$< z9Ry^hQ3@^oWDw`3UEHI~KiHL3Qak<}8T+GG9!&_6Yr6DX?o88jTGP-x{E?v8{xBL2 zhq}P2*q^?5daih;h7JV)O!;`+cpIT8UT0EgGJpzbjx#5WwGAdfN#oTTD8?iDtlxA` z$Y!<+N$g?F{x9IgzL`yJ_R2T0{jEbE$^QqxCeYy{(ha|WnBDNlyY?dQnK5SX51Z0! z3so?*V>$lzl^<_P?e#UwIfgv$J~oF}y^5Fye^Gw1#zI-_u#B97`4;QiCZ^u+-1-Bd zOpALvdRhm@gK;XBP*MokO@=j6vhAMJys=~FDB*oBhW6E$cRv}*7p!nA$?QP)-iB99$FKyy))XLOBIyxQ={ z1eeW*4wnuCI(wes3V%dIWQs?$UYuks@kYl$9_ zJYYpp#)@Rq!~l0io@utuvLf?=bo2M4c{;5wv_4tx_#GQx7>PYrtQ{1rJYjg0i>Ptz z^w;CBU&o=$&QL{ZOQUch29+|S5VO*(dEUB06{Dn#5?XjPv8Z2$z-S5j6pYSY_RAG1 z>HPW!Ew^62d6t!Bjg63JxYvvzeK3AkZf!;sD<{zUW2InOws8SsrVJ|!-j3^@109=M zZi_x&noHKF6ZGnv1+RJbW(pt|ZyYoc>g0;@7jMKPu^gL3|oL-eqE0xwufpGr*B zjqpHe|7O<}4L#$j%IYECYbwuwGMOaUMFKCf8B1NR)CAp6X~4;*71n?+5`FFhU`|~v z>vi)m`Qtr)5g#raI)9GqkfwD|4k6R!c)EJLON5m})M>Ax%W zAf`w;cz~AIFa-ujX8Vs=k*&g%FqqeaL7%|#> z^-uBMr{-*R4w%+N6p{Vo&j@;Q_WD&#SXBB;PWAfpoMmN%gTSM7>s$+DgeU-{U+Cks zz954$w#$kqh!@k2zFgivIDPswI)FmInQQRsK!(cv(Y(lGZ&ruJH}4`h*?8AOo?a9oSp1Dr$w*h z?}Cr6aTS%79Btu$G3V}*i#K~((7k8cD0p3B%grwv@B5VOw1Sn(5oWkB5UC%ox19a z#f6JY5~fCBqXxmjS@|#7Bv^de4~b+%g!%>Z%z|c7+EO$%^C6DaOjc{*C_D^l#v)Gc zIo|aNa_&Uv%m)E5i<)|TVXdwr2n)8KZ1^Za*89Q|s-h)H%4ij+!-$iMMvFLFr4$l* z#l>1dV(8jxcw6CCYB06kMn**@-7xJl=zdJ4ngwG;ie^*b(k%Lz<#Y$4>m*luGlt!O z<-+EFOtj^(X<&li zUs`vR!EmgiZx4SL|6wWQ-OlwKBi456e*7|I?sMk%H;|WyXdNvHy<&EPZ$_BXGat1luf+B&~kEx8)TSXGJ!%~%6nSiE5K2&K^*0t$?nqh@IQ)t~PkL+mpim#PNrU_BJ_n%IU9K<` zx#bHZD~r0QDpHG;$>UIWrFqgLPzdg#)Km`ed4T4Sa2G=0aEnlKi2>_#aA%}0Hz?gT zMk-&9d=XGcv2~y?c~%Q~nl)<~z|19O7HKB&NW~6`m}U$NHJG-7G^>KCSmAX9-dWki zMsjXthED&0?rRe0TU?)j8*Jee=>W-vBl4*4<8r!1_X0p_($CLoNs2BWNM=w3$YG?! zd09+?M6x{Xs@UO#xpr-E`d)XRc{{?!-r-E-r^BE?_JQ)pw8aV$AK;db*S{4(3~0CvBTX4(Al8`m)^yBe zhvGR0+a~A@b_0S$B`8ZMK?lJLbNM?JhT#(?_537n3~N4=z(w-BnHiW>ncL`MF8Nl< zy8~K9^kV7M3GuC9WY%3}Ei%r~|DN?_cq9KOXmJ)q%v!C-B@h-C!1oCjauU@qF$a&K z!r(H!dw1PvG{^$pyX%#9r6Rx}MD7f-o@ur*H=E$>!Rba>AXPJiGgu?}2>n=3o)_$b zMDN6FHG=BG8TLD5b@8ofR3(9lCfDQE9WY{vggRj=NHM5OnG4h#KfS~(d(aBuP6!<$ zi_2bjy@_*E)voe!ZGuX)8(4xz+mNx;$3_s$AWf8QrZ|4ds`vBD{=ATuCNO0q5#2T> zf<({4&!b2XdN<>~24Xi07^lLqxGIpMpPBQUJ_K7ilQdClvz9#s_QcMB?jEDY$#>3!MNSQXl5B zl!l_I@s)9MebTF!AO%RESx-CWW!nm3Gl&;pp*Zwb{#z9@Xj}-3AZ0~7zG4XM0no;gnc18B$Y&oCy^LdoU*B*dg{dR zi~=F!3rzVjnP%b@l~7cpRDZ!RO-`apF}mNDs~&+OVxvvzj>ZG!?Fz^5LtDk{WQsZ% z(Q~+*Y*u=DZLM9@nvR$li|biQNt4X8BQaJz2J9v3gwI{J&nV2kDFMwoafhh~v4_Z@ zfWs!yhvnJPw-02fj9f*2=w1Apr#4kGz z7e3R~bc7hAT;fwpd z=k>;BE#*xsEm=*h8yd31+4mSU*CiQR256wLqd6-nxK|!Inm4MmokZ(7+;Cyc7bq#} zpgC077^6u=A4Yv|Zt@**&(o41Bi7M*Do)?NO0hJO(lAdCF)5vY`a>*XEUE~;36S~W z{&=~=M36>@wphM+u__}->Mg%HibM61K~(~X0EG%ns7sG%&k=M$h6QQtR0;?Q=~67n$8Hj?9Ct@8Aer_NH*yL5%-X&N|bMh;qjHv-uwG1`|0*wgsy*%h$?K56R)HS(`L zk8+I*n2>xt>!u!3m(--`Zaer5-u^q=$(tV5@b%ahU8Ztf`fq}c1ald!g@;0*hTuDc zonZMYLQx_i&a(&|-l_9-xBMC6FdR7S)un)FJ?mKrsWntf-9t+2WXTE{uQbnBAvEF@ z?%WhOS}zsB$pE372HD|S)XcyxuBqpo-R|>Oy0jIpm?wGFBcsM7WdsE%JXEd3WnYt9 zcCITR)N*(_d?2!70DD#cBUK8wd!?taDwP+fRaLA_^e>I+mX`UPE$r4st~4J7${vr_ z9vBC?XISJG?URp@=LD*u%)i%Ccv9sVd6!Z+af7Cex>|m#uo!+-gf?%lMr4REHoW$D zsDxaNOE4_Ts{t`I?k{Ydb}+vOB;f*=XA{pnvaAE5@v$_AMEH_35Ug!C-4YeVFj$yO z@+q9qZG;f)*_0(00-9KYj8tcIiGh-+X#l)IuFL;a50G07GrtKlUF%Mi)jYM7bR^Sr zIs$$_+LeVpRxTGW(W*?N#2QJ+j*={p>=u18^Mg^6L0oE#_8?Y|lfdKk!YXZm%(Lg8 zsX?t8l=}tT$lcT>QLr>lFoFsIHeGl}RHi)%!P#?mVNPr5Yzrc>b~Jfi>IyYcDyrnary>y|ezl27xx-M45hvf}~3K#*Mys1K;gJ9Yc>?>y&s zEriOBeD%J5DBG$t^Eg-H&W+LAKg^hukhl1}=4LxnO)@+1-E2?(cU|Q-HX;fwLb zpws46Hrp{YcTaeKL*#9(W=}AQ6+-2xe9y&ZnI}+D%PDLUuRqE$f9>6hUw_jrCShCy zRAYfmvX>zS$YJ{=)c2(ON?A=;`tIlf3u=^zE1d4FslR-f!0Pv?H&RZ!ix70Do}%8_ z2{&SSfBz6GhcZZw@tkye<9EeQBZ9xEUJt1L7UdZj)sJ-?QL1<)jW{1#oAY+Rq6#NiE3*D;ot8A>7>l1drLcLcQZqyO_OQacHS8 z>s?fYCrIW+|qdgT5c9f%%u*Kg*M&*ZJkkE|&v5=o9-ZM2L zupm^0$avK#NsR!-+~W!WoZ@+vPuXqB?Tx^B3;QZjbmFt$`Xm-nZ+KpK_c$PFi1 z=p$+3Z+ap}&Lbs#=R@fi^X(`Qx}h=XP=waQ$-GN8D9w7sXok}19&Z7}`;*0ec76zd z_S(~hZ=rOTJ67KSiS1}#ay?1aKwOKr8U45<_L@!;pS7$uV#M7B1um8M97oR%Rr`)s z)V(p@EG1|S%P*BjTRbqpp-~juW;|V~3ycy3Q7fZKdrokeBr+MMrOSPkEedaO_bZit|<61c>`HB z&kNOQ;DiK>BJ2}XkDaREeuA*0C7w>xX6B_`Z_>u`Q9VZK6oi=3fly2za} zS??;@yU-o6j*$AA5|E?8h0PPAbVB; zlBf=1nHak{Dj=F+S`JoO_^3GAtT-&)4ia#iysax7b0E01CoO>&??Tt|Mu3|y`<)%W zJUER@d>w>xj1GKsq766;8qqNlb5{Tl^oTu^uyT9+0h7!(t($&IF3$Y4L4aN+aKpd* z(ly9;gKppJh|68bA%8W1WF!7sl6Cn-Fc09>Heo_Yi>R+B*#rA%LvN-pfn)kWdRY+$<_ z?Db^5ECBU6M8Uj}BqNamBqiJ+p`+5|n@cre*VwvpE)WyP6$13`9;hJd-M>Nuix{S% zc)^yT-8cJ)kN_^j5XK^%C=^dNCKZ7W7l^iib4KD?UHdYHyoTKfYD~8wcn&C+mLXme zktRE)3HO`sxR@fksDSNH&hMq(W{O)mkr0Wv0rda8}}OOeA{^25WKisQB?n3bz9dh*NNm@tE4^zsl4pUoDk+Ah3~=T_0(O z0f_A^ z(NX!cBq(bWZ;gs_R9R}TKK1%ZR;?bK9j9(#vd~pWqTE>!9~&Ka#eHEVZFC#;;d~w8u54E;7J)&JARi zcZDwp7gjAy>~o?+Vnlz-az|s}iell=+2$<}bzYdO<=V2Hq?8el7v?#Myp+l?0I#Y-qDce))bvYRFCt z{uT%Mh(5O_!+V|`=wJ!*HR`rH#{f|h1!@$sK7TWChb4YTX|{ZqB6;aH6J$v;Frz7G zq2Z7~>{U5gt$?iZ%U0#uhRLoc#CSaM6^NeGpo4pqL0-Xylq^$ZjSHZia|l;M;Q1t} zNWuwZ*W&fKHF#o%*)YTXFYUyLkqU&DgjARgX|%1?HtKQ?KH9%1E**7CfDWIY_SLl^ zCkDe7)6{G*Z9HO4$Osp~@v(KB5bYGrZh=dBIFMvf65-^3C{%W=H5z2nT?iooKtg4$Sz2Z8M!_A#pm z&yc_uhFg$keYW*1ugeNN=K_v`65~8mG7V}BaJFn@%%W7>q#dBO>#{26rms)PFo8%~ zI*2!+T8185HW;eku8fqByKAXbB_j2hMPFL}nvx`{ZkoVw9g>6qidv=T2$ zs9mz@d9@O$y$e33Rk9F-zKLhvV(F&vPUvl>C^VrJ8+8VY1S#nBdu9=dO)jmJ<&ftf zU3cg~;?}|^k9g;1j4sWo6Q{x%$!pRpp`Qz=9I3vu1ies?z@M~;9OSP_P)EJHxxI5) z27*Iv8)sDI;cC<61uX1?QiMG_`i{*`@Oh3sNBALN70_(Ls#=bW=sm5HpEw!=Vo@&7 zH^|jXAIBtB6*suM-OCn?r2(uw#hRbFzcZ5c-(QJ*2$z`e$zzUv%|-n9EvO@E&8$$z zE{+OS+388cqyyF}(pAC=H!cT^mK%-ccWx2dm@9lR>=&SXOg^bd_#u<2V2)vbT$ONK z@B|o^rD8Oa%Lhq|3l&ucRv9K{THmfQ1;a0R9Sm7M@%Q(kea(PfN}GJrFCZcO^P$~4 zEzC`~KQ_5uGG(C*_Ui3ibUOck>I3I@{#`1)B8XU{z2*)qy3lMgmC!bJ#6fC}GVhsR z`|qUxFG_e6!QRv_KmS8+FMGu_Ga9iGtPt?K{LXYoeZ*`(y`#*w|F^V=f=!T>JVJ$K z^}E^Mi+%W`*w?flHu<2|FMu5IVy@p#6$AvRXVimX^IRi11^vqy7rxQFJGC^=!Fug4 z-G{BZz_!7(4z1VVc%j(QX;@*(Z6$yGuk0#Fm8v~e73I=5@`O}C!0K4>j7*6R(S(Oq z8tX~1%syQLw!er`9}YRDZ#%#;Jr1!HLW&VNZuJU8fO9{oL%}q_rbO#mI+ovztc3Xm z6vkL_fn4xc%@AV#Fu=_J7l0nXsyjX1RPx1xY%q4tQ4@iGdy>70W(EfMyaS&G= z^LPz}!sR=HT@y8j^XCIviOuNt$V1R~23Vc|d0Rs$3k2$lZfF(VJ@^#P`8NTcm|Q-t zUzc;^@uigaE!;ZsO-?RaprmOuh?fda0F|NA7&mXxy?jV*}ZL?Nf`yU-F#2q0~^wCIvfMZrwMgH}=mpC7r< zKBmNKshiJvt8EAcE^a*0<0XZ^Y{g(m-17dg%58E7>36`6a*gS1mZ?4oy{%1yDD{<`UYzivE zIa@M`9s>iUb>C$A8&B>_xZ$q6jNZ2!>kL3pd?IYS^h|SlmjeSRWNb_+YOa zn{y2KWsVjU2`XAI7zQ-712GwkD2-7fKPx#1>Oaa@>D=ET{`Qh z_Ea6n0n^&NACy!}^G~}2bRi>eG4XbQD^$$-HddEv;<(_4=kfGbV4HCDA0;~nz?6s_ z0^Y*D1P;?tWQt*q7N~ttaohoIGR<5J0XRGzLS@Af{RoT3WZs4FC9O!a7ct0F5SFpQ%Z-s{E+z%eZ@wSL9%FK- zU%;Z+t36|3d^&UhGO(2+cOv5NIQxF?v{hkPU^eF%PqL1vWk1H)dUrI#^h@_I> zgbVdLit8@N?l!}-IdvF^PDyI_t_I^lM{tU)=~`Ea_rnVjkYdE1H6wCTx3R(DfV z`vtEw?1n0rRDHUQgM}i4=UQLe_z-0V;P!&N?iGl{wkJjV8q9aIL2U77PiOY1k2ZZC z`hwb8v}yyt6b&ZT2thi|w3Z$cO(Vm}?5NVF2&XfhI?rF1A}MjTzW}B7E>K3sq|~(~ zYx*!TQZ@qf5y={e1L#|y6)h3@4{7dfpvG(^Fqc-yG|aPbh$h*LBEENJwP`VM#PhZm zjEEeuu?{5V6-|UlN#Jb#qkTaqtO3*a9+U*n<1eo_o_f`pCQ;Z}ntTaKVQ6VHB2xPY zYUq;=8C__{gp*_$fkad-<>ELSfaE5<0_5I!!2F;->+tDd95Lnr<~kU2oiQC$;-Swk z3fP5z7ri9}f<7r3KT%R1e)hi+sNWg;aNFeJ(_aAO&q{5$U-`X8OpMhZ9pd*XYwN{2 z6I`nCcP0?B%Qt%5JK^d`K3 zaY*hd$5W^w{u-7K&acaoWVP(*SIPI2I>i*F-6CO&7P6P<5Fm|srQ*>2E%;;7LjRyU zOm~3$qBcNr(We3M)LKWwi&w$RB;`UUZw<4sjVbHdXw;Eg<0#B0$JLH(O906DH>L@ze9)I-|<(?cHv@*tFJiX|?5q z_a5hmbR6ocP;dP99=BZ{9w+!sy*TDd#8zIMj>g;o`j}s{US{rX0G=BXE>>YIZU4Wd`FTkMvAu12+C>}i5msk^h$~*vtLxRjN zo5ZbMj)bbc$sj`QEQH9{Vd{#c##-@tet9GsvLZty-EW&v2V}^LFHU~pY)+ee;9*rc zQu?>jsL`9+a`>efd{pm6GcEXW2V_gxF+p*GOtGRM5eO|pD3+RaZRa;Q842g_M?hmP zo%ZVAk;1%xm_rTt9-i9%2fOGFz3o{2$ehjG_rl86PC!g$!zwQ9-KG#3mi|F-FIBW4 zE~noTV1efI&a&3kbb)C^l+GG=jmLc$p2gP( z3}@I3K!J^uIRh8cqtgr(?!_aVuzJsck&h2tKZsaJY7z4#X7K#Lf=zZ>zhFG3I{q?U zbQQJne18Af|JX!7^@>(ltoh7Y$eL4E9`!r^H7Y8n_4W6aX&uWuH~soWN0(RsTgS+W zD0xeL;Xhc@ZtSjR;SOt`H1?*OU&8-w!Id!BKMjEuA6buvmB;9$!HUEfv#TuT6XKAB zsv&=?0-U$tg?%_aDCz+Z)iKfScG^*Zdq&h#j`4gxmI3>K=eckbfTqW8swr*)8_MeB z0v%y`oZVIQl}Y_^G*@=qnv5qSdNa-rLU2K_)>rmfinMUg=b9{2kh|hZ$_NIBKlHZ# zwMc&wBsO~dzTv9s=qauO5?)J{=cAw_3jSO3Z=YjDoQB9?i_xDREOh!8`I)Y1Ii0(d zHp9@ng{GTU;xf#`Yv#`DvH_}h^m|NewLmg0_68!6;={)%m376Ha3)$U@v_t1NDDa% zFoG%IVfn)9`7`}(3hsye9pT5bf)Gd$TzIs3C{u;Va?329Q{Q0egJa=j2sKH?0{ITf1-UEO1nN8V$mRDPT2+Xlp?PUb>LCnN3&YRE_Zu@ zAoN>|kGpA>FcTU`A*1Iirt`MT)h_u<+jI?7iQo*iULCTdtw^G@JfSuk%e@1lt1MfQ zlDr4vak{4rY2!cyhb6(Uq0tXDTC10MET4S-|y?nw!7&1Dkwu z=aQQ3iEV&%j4TN%pNHscgLEbDEUH(^$z4XJAADI4uDo{zPw}%OExEAAGf)%q95-cT zNNFn6ggW0_NfOPXxe8$`bquqKXlf%GHttWe<2f#>QSCU zPPxQ^aXAv~0}<9E4vEP$YHk>w1leVG^*Se1MKY#Y^IEi?93=umQ5_Pr*JJ~V3O%$N zoR%SoJ$x}3n_J4tS5>8W;eDMGT=qBc`4r?VKXq_`q!L?}z>Q2U(hySZHG_kMX{Y9m zbh+t^`T|y3*Vq^^9SQr>+t;iFG6A063zwq{^&vA}}pCwnj2@ z$#C@1?O{KeS)id(w`f387TpjM;hg*0OL)V@!z{0|zCm>H-rr@MzcCU-8y=O2$2jth zGIt8wD%#|k-{ltzbueP-8RiIXg#gf*NH_pMf%^CWGJy%x{o8(G;-SsmznJ#y^B*aH zb&!7&*O)W;Uy@lEQ+Ozhf72T(l?gt3FD}XICr%}LoN7Ros)q7MDL~oL$t4+d6B~pL zKmt0kU)3?`i8y)e1~L-dwe_8SAw^k$isA@iz%Ux|D!#eNRZIxvBmKxP z(Sy%hl&fGL>R2I$+X>Kl#ya9kZy3li|2oSdL6QCk{I9Ses26hho9s5!e0b@W!M&u2 zBS#lppd9P!l)0_}Pn!1IZ8eW!Fln5vLPx6$iF_*;op&es41E_OId_=jy`AO2RND7t zwccyl-xJA#pD$`8i*%s?wrIA_{ry9XZyn2^!maZiQo1c#eWoWaWLSS z9hV*@KPx1Jq{)UFwDX-i`CvA3I$D7M^xn@bfiW#Yd9f;Bm%^NP{}6(IC-r;nsvTSN z{ilCbY1MTVdOdqs_$_}v|L~KVw`Zn)Q}RBV+i-JudgRRcvr4K;x%u|PPmHAIT z^wHdwo5QmsXMC6$O@GVy#})t1_^*&8sLwa9H@YUI^Vwfb!xZ(RA`A2K2g47Fa{Gss zz5Z$Pcqjk**CW!a7tAK+ZdcydwEP#653QnwLGa}8((lgylTbBf(KKTWz2w)_ln(nS zvPjX&w%TFW*O28BojM+I*jO3G7eIYsp;!9gYn13-4haNHrJH~m7dd0ITB_rdOFo&Cqn4(-URb3m`p9Zy-lQ-8Ad2c+Xbn8XtD`}Ip4u11Kx&}4- zwm~PUYdwPin$Y9$(E|4^c*(HxkrPn7-11lo&ZtX^H!Bba=Cbr4pYbi@(8>4(D1P__ z2>%lsX}1llJ>nK&teg4(nsMl|x698bYd`Es7OQF8L0B&L)lOTM&m_eMfK_(PHVK=W zMSTAQO9@pD7cLyv(0se8_!65qWuTUEh!|^sXQ}G}-SB4J1!UQ)rUMZAldLa7i;9qg zkw@mJp}k5)+G3v+q&TYdE;%!9ca$vTX19*%9^s-@HE!@fjSt#*7V;5JWS)mth?Syd zJ)ri2-eg?BbGusdj&=nP%1FfX;lGjH^hpsh>=R(Pe0T;_5N5hO%ehkgYVThAUf@5k zsWu#!Xl%yOA=>X&0v~5x+~+3-R6Z*=y>&QX==T8KE0_{lSooE|WWR98-uM6M>ZvDb zSI_NlRbB$t?k{vcW2!0Vj?8=&h)B34^#>#QH(U6xu!a9!BHn7a>0Ws>!MWg{R#BFR z4MB}HoNrHM#ymP57hsH~2eF}rLKhXcLdMk=hL^8R9iOleGU9d-63ggRp&|2Mey-0k zhIs!!?7ewBlwbcpe$8rT3zi+j7e}JE&euXc9>yM0`Dm*OH%2g}lT)zh^wUruTvnysD5{BV_DcB}nk( z;{fY+cOb&p2!#NdPgPb)m~#JQ) zgxiHX&KA!;uUJ8qG7>$8z%ucxG>|vEm3k7@kUsK2Sl4>kG3I2Dz9u9UA=b9a-mM9=NK#q1bx-Ly4Af=( zf=t7E8Lw*TEqN_D$CKFaiWAXRTZOucp{fytR+A;%Zb?ID`P)zm_wU=U%FcmANQHtX z*U_YPvG32fmbAU5bv{xi0f%bNJ_xoBX)>PBH-7@Wl2A~c7=^b!9i7j5pKcu@7TN#Y z#~Z723k)x*d-6{BJAlf{U>g}ilbC#!pj=F?_%W?4jOL&gU^IUuTlTiE>V*T5;=((X zEVNghDUl7s`_l2Bq*xinSOJvl1Wy{>b`H`aSVGF%bNySmStO_&WyTy52-1`iD=pDu zRy}S8t{zy2a;mBG(6H1ve`u^6XLiQ>O3!y72$!S3UoIIXOq3yfiYwA;q3RxU}p@>ob-69XqhMbzwMA!M?Z!s0A@Pfj8FC!YGm5r=l4yX?eh7J6XG zSMq%{i-Wjc+_MBY7*pR$F=a(H_0;VQg(&+{!15a(eQ0XCI@k==^)^?b6!O~OY zGN-z)I82Qr5mx!UY+Ef-vs3q|ejJV{!llk((5449q=jedN0JdQP1A-v1SL65v!T;z zIP*)vWP7b5dhqIS*-yk-4a?IF_G`s#*NEKb_MR!d9D;x}Fj{Raaw&BUd;30uXIqkJ z!;@7_XL%Vno^U_lNe2^HsGPf}_c9k8Z0O=6dev|Mx+bSa>EJy%pIH%B3|5}y2q=Td zCVMl7r;zbwOqJ8BjBmxI=<)6l5Xhuxt zZI>6kYwGp~Z&qXuJ+6}zZ38)`4z=RC5uZEZG|)y6^^0X>7JIq4VbD`74jKG7@phQ` znkHgTm%A!FQ?c34WFtrWim_8`1^KudUw!N+cmKqDafSHrf8_3u;gG`l>@s z*`W-HWvj31^k5|q8TvT2oP9`~E)ZLo?3L5_w%t&sQJ_6;*a94b9?zg>)kfB42*uz7!PIrCXi)h% z5Ovk9XZQ(9$7hX~J#N159zfq``kbqaWeRtuYPRhHG#_rJn+`>FjA_8(_RVcCfFfYxL;E#UIAcbx5i_U+B@ zEVPxRz3@bHIuJg`Yy_CJtWOEQiGcCufVIYXdcN=&0inlmuT~-{-5}bjA`rCu))AFj zR3cjs#^M{MwN9#lY%p;2bZQQXcCS?lq(7|s6AL#Tu*7noHVA3yyFO9*k+9g$r&qzAO+P3DhE$!m66!`UYNO${Wd$fn=5EcnZjzaevkc%`5$Gd8-hkMWpk5qXd{>CO1uh|0xZw&e4hIj1meB-jg3&+cFPRd zaF8tGzWc`q+g&^?w{<%RA8|vr>jYae8{kfo3NNstSA4gVEORCJN=`gsD7}Jk??Yu! z=20kHP$7tSJWMYdiqs-4%-nhSp=7F&}50PiLC^`p!&u$u_i$Qm!9GRXd8~=Bk!7cb6`*zfRg?=(Ab#P zQb1~?A475V76P-Kqy1!dOqDZ9q0VPOxtWrJ;k>L#=6h@JYU^c4k*zY*dXuTW*WF^( zhC0SZtAutm9+8BqOZByFc(drVKUvkPh3cbLu=ADzEq7I?zES6Y=E5^#pa=w7P{0(fmZe1^A6x~RK>@u0*vXrSMzi3k;* zK4{-?K1oT(b|?4~DyKe-*q{GmM?`ser{Mt4UP(~-C`kW3t?ji0V|I@DJft`W&X|-G z7b1JU9w9FHp3Qpz${U8-d2Bd5xnf&n8Mad1wPKf;zh&}OZ+cC zgv9X!7hP2u5-|7nHBb-p0wrL^U0yzO7-pBzDT!FOa1aeVi><_iB@3RLa+GAiRC1AQM1?E021-m@*8v0sb0rR65bs!u;mFFoaJ`& zuFOc-DhOmpCwH`Jw+h#siqKweQHl)er27pioxc-pkHz|)DB0s{Vq_N^zfSTypcD+^ zhER(RiYw}^ayD>u#PB?OKs$Oru4>sTX&o#t?ju$^zU}jOAmAsH_lmK=vEX=t3KkejP{ z$!J-0pe$bbs!~nQE{L$06CZd^4r?1SZo;%?STKO!n5hvo!;!w%=1YOzTSvaGTt+Ca zT`z-dPyGa+)U6#{zWOI>3RU(GAHKeTTetJSbpC$md_*|mxi;UAN%E_xRo_^9y;aUk{I1AH zpJ-_?D{ZfJkC0mg4|tmth}q;Xv$#ilXz%acDOk_GA0}ia(PLI}4QzPh0cwGs#77=p zoF{m>Up~E*eLKjH+Kau@;A?PLy=poL-xXlja$v{+%w23n^R1DFTkLA~dKPf{YB}Atbvo(1#6*`V`gH z{hC*-W~*NB(+z#39opWvks_37$g+~M2az<1Je;#u1MoCl;Q=*79S{l6#hADey>4}_1xaob)Z1~!lBmd+?NpyJveuOV znOcG#`QA#{Dr6^vdurg>iW3t)Et5ur#iPOzM_I|uf;}|M!>@%TaLxO? zEyV%*VAi@c-osI0Uq0B7JhZB+A1Ew`?bYh?4dER7LYa+}*lRStx!cSQi%gNxA>fde*eJ~qVa<*( zy|Y%Tz2uY|E6Q|wf{$=q!67Z@&7Zya`o@L+=%85(TZ_q``zXIKUB9wpiz1~DZtY}# z8fSuG<3_iS$5Qj@`rm=zpX|XL(aHy;Amw3|n*7kAw|*pcYW!0*q-}cG`kwERWSMA= z1&d<6DVs!y@X$Np_`tZ~0TnNZ(>EY;8DK@7S9<=}O7hj-U9+ix;8*R^qNoffY{Q*B z!^Fo2vyMNUn4HV2N*|4My`B|I)xe$i1WDSK30a>F`KT+_DOF%ZxK4!%yBnr@#I2QU zQWUGd5D`f@0|kLl9rEtG1eU)2 zlA-u%=JHtsoR)a`b<-RDKIm?DbpYh;BGF>%m+B0y+4&t1d-O)qT|Et6+UKjOj1lOD zAS7sJd(WkZn6EEmXlR4mybr6v9j8aSL==Jb=N!VdIA)`8=!%e?(@nNwx~*7_)GUJ_2}GZ zK;60UD#Lh3h$6QT!IN@;=#EGVPqv8S^svr0ow!@EtZhwF2RVA%i-LFUtFa)SBlWnG zJb0QyvYwpIrW|34I)i<-KV{HbKs~H1Gi%&y{eytPR4a&RHSIu2i!la?@u%&%K?8K^ zh@5TgkYhuRIL9%d5KLVa?hm zVHAq1!xr{vrllu>nZ3yIT}oLB;H_bO_1igAMF8Nbdz-|yg}e3DAUzY&12gK7&^=v= zw0osS*(ZF@beCcce8@Poa5E}n3880$@jTdwt8{LwHL3wIjdd;tzk(p<2aG-i(GSimU<6qTJpHm7Ks?bI8K1;@El3|Lp- z+43W4r;m)nkmU-^#e@Ci@SwW7)0Z`hUm=b@&OK1 zKdt=FmY*ZK=(@M*YN{ttDY2>_iTyz`?DHSCrg#tUBK&}y9QmAYaCFLd<;clOnajHc$Z4XM-zJ{h&?#!MxKkK}N^jGu7 z@#46RUkg%~4C%EZ`KH0$f~&b!#!q2w2J-txB%T>R+#?)yf;m=`d`em(o;2OJshzt{ z90DIoEA3b8#1>?2VyJ*%Y2|{!A=NcONYU*e_Gp?=)Dq4IQ;(V2Jn^l)d?QAHzwqKEPmo-dzN!8k344a15(F8d^}!Mi?v==h1L6zJ z)o;RNaSPc}Q!e>of@Y2(^e&4lr5|=`8VXm>AvTMSaAjYJHXr1;??9EBE-)=D6+L#h zw1o?T`$T)5UoiiYELBbG05M<6M$`P26i4GZjZL>M$E7CRoLV87;*4EEv$>*&jxKD+ zbvQ}KBc4Bl8z#Z-Y+n;`h;)7mJ|7jJdh+>kIo9^nm!JsSATgwnC**GF);$j%MKrnAHBOk6< zHl@tYk&YmsmEpg?Ms@1)r%g0y9o2XM59508|eAYA=ilcE4 zS_XW`Gj$zQ!eqHT>L$t|DAc|(I&3!xs5;I(z9 zkywp-t(S!D24V; zO9Y{4^t-mEcYx{#bHw@E44}^1Y+cbVzwu2HVNe5Up~w>mr7$ZaO9}}4G}+%)Bm# z77Tf1`OJL@8}#}od%K>~+zr7xO(HNasJU!J(#bXj#TtOQ9G=p@uG*gucUljsx_TVU zrTMauTxk~7pE;$%?$PnydUvxs!;V5t)E320ERMT5`GPucg}T=bq^q zx~^Er)F6yh02d z8AQTWpCdhzGH3%JIkU37k3%GZ{0q%4r_MKW0EBXaV_eIasDo+eu>j*N$9V4wgt4>e zg^1ga1?(S7`?x)Wn#7yO8bU1)iuk55#CVuZm~3KRB5~m$5wl9E$@AFxCpr@tKe+4OTeLF?)Sy8Y#zv^p!$iEe02IXom#IUPfy*C%gp$z;9EZW5YU2c&0i1c4){_1#fA7)@SAkp6yJjAr>F>>kR`X26Wy`2G@2i#cuag zA6)Rp8EvovI822nql66{fDWhjBle`cvJ^YuQLZNQ4%UhwpN;0^9JMgebE!vx zX6Sg7G1o7eEmCpv5_Mn?e&`FVzV9dV3&BFE^%9Pp?V=T(p`b zGAUi*xMP2hvW~5drsEr1a%S*>n0r&_84K486-@5;uy<@rZ|~Wd>)>dQK}aVGzUtMG zYZmt(P0<|Yn^euKE3H+kLng%GB^uII2t-PLeIQ%itGxA!ybpBuhxo8cj5L<0|v-RWH60T8pDc7Q|L$hQ1K>Q>FF=@ zNPbuvNTBeg1a173rq+u5IIl|O_+l5qIh@jv+3ZedW`o^j<$QjMQc(oc67WiDW?xsJ zk^uP|wWacwqI}ff1H_FLmG};f#{U$&EDQXs-miByMhFGd&L=Q?P58Dy$aQNyAXmC( zjh={+YcWXBIr+(1`aRTs*bwA1$>Db6d9OKNgRe{fg?}O&IRD*-8b0Tzg?_k~H?D4U)j%1t`hLg!NUR zwF)dczN7>jQ%p~kB<8C&xwqP%t!Od<1F^a?mxrX+D7J`f)Yk5dhFyduPRFfo zI;a@}YvH~}hY-h<-TY5@o=El)SKW)wqnsI6f2KsazHNvN-yLNVJes{K_8wFaJ`78C zJ6y!MJDM!6McOa8to;y^4jY!|(YG*?TS;5r2zo6!3P;Z~F^Mw%zEa3tg553CTqPJL)*+9D4b46{Q&@dHyBW?2>$c(j$gU3KtNPzoK!I8BwkM?G6 zG5)b!Hs)UiFIV~AGb}3mo745<>hDgKZ`ZyR-v7GsN94ap`H?J-e@xVWr}>%s{9lCq zy!*!$zkrqH{izPm|9tmPk^e8f&wo7e|KRYm|Ksi-HT_#WAJ-3Jr+j|do!GB4y9O@C z+yXT-K48B)`G6=nLnwAfn5tc<{83r7QD(k1QA#nVJ|sJPn~sfw;k+ylZ$~o=ftK04 z0>sQmcWHaa*UZ>lO&RT* zi1mqNqzz5T=rRT{kk2oqI14@)Ale;XEVRXCHd0!_b(+R_vqiU)&`CT2VMX23+V4`+X%7j-ol|< ztLq~h8g$M%UdMwK^+UVK62e#gII0mF`cYa53RE!d;F*CJOqA-x1Em|gFJPjYC0-2# zC;_VP=mQm$&V`I2qIWwzQZ3&}4CzP+^jpo`$)JeX_rE@lA@j7HM9S9= z+&4O5hJNLH+U4Z#T@RXtM{Tbp`C6y>pggu{Og$rb;xH;9X!-Ze&lao}=SpjiNM$4a z@B0)lD^kE6@bE7P=?|GEcL!67U{;#fC;HOwgx`shQWHl55PUY&cC-LAKRAiId_W__ z0^h9geli*>=)p<3RV`#%cBDtJzb14?0iC${6X~6oEYLHmXgy(MZ?wicLv-Nap_hN! z4CC)+iUAmw@vVU>k~@vYIX7`9GzZ*k@6J=ZTWQ)YH0*YcCHLV&)uz>(r7T?2=z@IY zS4*e}5+^mGiAY}8XFDs`_BcKI-5+RYjO62G4x8PSJ!%8DA`XZxrz=d$QmvlC(zMEs z7;k=j*>%IW(N`EtTPT#BWQxEB5W8;%Y_c z-rd6)L3UinL632t49xE@mHMR3-ix|eCfswl8URbAakOA%NM0ivp^fg}FL;~*bBARF zi6taP*iPV-cwg-hqqWah?ov!>ob{>nG+uV9!8@t1LM6xv z@LD$U;tU7MP*3O0Gd;LG#pR>@YvV7VVyAUUqXpMgz5Scr6w=aYg`AEOdf8keGCfh= z$)54#qOf$|7OQK}r+OOVpO31RWXOl35icMrgKJ-xM)(THaSHb$?=+qEX@iX?cV&H8*llPrJmFRFzq{^DGA81ztUR9C&~WXVkPkh4^5&h(qkDNgB}ip6=th#yVWKb@2jKY} zgUm}ZZIA7TX`~Rr7n6q;3vI8q>^X9x^XSb3TSmV9S$6y#Xbt)pG;2iTjwQ)rkM${U zL3R(Z^VUE795>%kALnE(!Raw}(;igiQn6sZjNh@`I*gNSjoc8^8eR=o7U1aAR&O9- zcB0+ZCU%ph{QHUyqfhvYWk4|1)Z;Dp-9tAiroSuxv!dc(G-lI3JS52Y`Ku-4rKZ23 zq?c1 zcPY2)Nmuxe7y1`J6l^-+eCFDJZu}cal6^k6Zrmr)B6}rnJ=|$m7xD{#Pso<|e8PJL zd--_RyXA#TF^s1_g@fy_zB{~d{d}Y33WWcUuu}hZU8@s~5jJM4v$v#OkYeR-c}47Q zhwKq#I4p%~j+TV(hw7Q%KM)8@b!2~%0K|cj2wN(unN#AK4ONDdLOiM}*NeS^Z5xTd z_OgkOiRJW8VUggoT__Iczf{DOWu4NT0eD#_0J&FXzd!bA= z6x|1WZP~3R1d2#vs17!pm-N4+fNgiW0nvI%Z&auX$U6jT25liOBUXxPwOAP<@Npd{ zXU$H@u}qTs^5u&$j9V-Aq8=Z5Hy3$B*=Ip60~Qp1oazQ?b(uApP&H!}_q_210deQigByO;^($nn~iuEloK%f{)YAI{bX&!C*RdyM=yohzLU9D!SE%%W9R* zh#gg;WhlIUDRZu4amVldZOP-^b0cU~h=8qp6!o+%y|)P=iG$iw{AqerJl^=tn>I1s zMu~*o+CX!uknk}8SN61#GNuOqL>uK4WWwojSgb-=i`&@t= ziYAom5_H*0Nfi@rGj#R&q$pduI*AX+pY-QYHnF*$JOpY`?pCo}iB4dCh%)+Na!*Hq z6252i)^2=$qBaM+Q~#Qg*pL)uw~XB)4QV_Z2n04T)_vfqA7@z8AQVjcVo7IwX&b(tnP0MPn;nU0a|Kd$65GI)M zusvbOxoDTo=v%qHnrea<#+`C|dNAM*XgHxnD0np&Mac4549=A$ULS;eRhJ!r0i zNmpL?IxtTO&zU!%`T7_2hdw#7?HY&;3%hcLOv@e53?XY7X~+W(A6bCCfo_`iMPSF8HOlE)+4Uaj?s(I zB>U3Z3eo}6sMH&{s#i!zhq%Cm+*mgea^PTPp%X2*3XISK0x?l#Mj1{)<$J6Xn&yZdKP7%4X}o11i6F zM*h&$2Uh?YWANLYxB5_VU`VR_BaeI}|0plX*l}y{9qNx`EZp})owVs?8?-XZg;SN= zqksdJfv}`Oq^HgqNWxUBr6mlJxpde7fHRPewF}3bqSv49Q|`+fHxFz*YIq(pj*<1M zJKb&&;E4Yk)rO&ea%7wMD_$uxt2kyNdO`V!N^@m=DqTd<@e^LNl;fZrg;`)Jf$yL8 z_gGW@nyMlAHsVX7%z5uGBdN{-#N%?2!J?3wSUn_ECQ!IXCoyBu;&zwXno7AB9YZW@ z((7V0K7xAUa|}INmMWqYhL*K|FxZYw!U0xX3SpT#Sns5dSqE6ny@DCA2ClKe?7lAu z$PrHo-)n(*YiqnrO?AFLMjg-+Sk(T#^L%+XSIlF<&%$_z@AW?WaPu!am}hC4)B0JC z;L~a)1NHYpva+P-5?daf^F7izHup#y!b%iqhl{DBF2_QvBRW5fWpP3ZjR!%golc3M zN&q&l8M&Bm_b9ub3xAyTUSmW*294B7#->;>M9Vq;H@7~ehjSdO>YUp!2dSh8Pj@sp zlW|>gKC}L+1P-ldv+7)M&jCWX6m|L~LN$*t(9Ge@Fzs|=pBVOyVvSww$9vL=`)Rm6 zoywNg$27Vamydi0UR=D_{fvM>;AID3)@+j9N&*EvqkH(W$r8m?A5qNMC zHrBDp=eg`$f{IVSt(JKEC(+?&i4s%NX(D&u**`|o!jGM&Ua=DQxQ%njyd{Gu^e7S{ zzJ`Uot5SL2r*>oKb4@+6y9dcvm(|4c_WjsqA78eF0S-#EKxozVE zUYbE#=-bc?(NT~?2YD9Kx`F3Nv==@SA*2pI+nr&(W^FX74q`Rzmp~#Mz&N=d4W=8? zSUuA$oAot*p9}d4v&a5wEGr)$v5g!jRc#`KuTrLgrLCIU!YB35iwT|cU|5UmPv{fh?k-kOCuvq^wA_KWi?M%Yop`t z(wn2!raWPZC`=HgBG zY*^Gx$3zPWi5Ydd-GOpX;;Y+j+L0hMdRucJFqP!zH^y=_?gfS~h(oP&q zAdMG5VqmQ9B`XAFk|Z6%&L5sYU{Ou`=;#?0=NKIY@l5;6f!6lCj5?6o*BgUFg2F3g zm;nnnzl{77VOFcMFAIe73SZ8zz5jaGslI0xr*9nIcyPIL@te!XrT+x~KS-16uu)hj zVD7Pkakp5?;<6HWhZpaY4}XU6=jBLGh04QW2J3ZjiQMnTN6$yn>V+ zSA**j&vnxsNZCh&Jko2Z<4B)-FJyUge{}`LBp)PfDJ}bCBYAskko$A7Tze1woC>gG zgh#exkBS^SVYJp2gJ4`3P7{>~jz3@=2v?O(?M2`%auo|}=B6I8UnoQHH15IXF>3T6j_e ze4)Pjp-6Y**HIntTTZh;3}Z8=E$XZrC>^dSTe4YIx~HXQLjJbsjY$Rbcv*T${H@ne z<=mcH>|0D_=uw0l#Ww1A`FLN+=G+$DTj+Nc>DZ5O>ukRL_@Yp>UWzHMx6hCVE@l_; zEugOQTqYe)oTiZ+v}sgPkO!$^)1pL~C&Ww^Jzgh>*t0%1nbe%vY_C;&J1-5l-cYA~ zyhduYSGGD4W!Q9e;F+M+C@!(i!ActWma?b_eUQ2>{)MoTnAmGGLTJxj-~%Ehdp%Su z!=0Q;km=c=zD4AD=Kd)2(?QJt+l72IUd=i<*QeOz{Ns#OIlR;88cw$@Rz_53Y<_mtYCjH{xLh-vMJ3LMkI-m;+y&6s#9wEF5bDE^^dILbEN82$iWP;{wk|9 zI+nCh*}Y23Pgt63sbi(>h~0*3WvXu+1ug0qNMh{3j22S4{FvwY%;gvCcg{rL>R(2 zeWHgPJJohD#7pW5UOZ|u@3M8t0`tn^`E&zjV4FZGMrJ~~Z9r2F{wS6Fp&@TDGetF# zc9iOm{(K?ahlT4U8ixw@f zeFy?|gQU$L{5;mE2jOy;hozgPHkVlJmVSJo*7o25l!;!28x1EG<#S8PI~Vb=X0t0(&B zCmx`aiAusIx4L6oY2Tm@@iarmRYO!JjKlIi(%ySECyjB}wxKB&1EEYV^$K2`T|h#3 zw*~sHPm7(=hDR}TgmPT^BL$!Gf=x61xI<5*t!_~FGC%2Mo}n_@FC<<{g~66Fb1y%T zp2C>J5OHu2B06FtVr&TJ66pb5Yh)T48~1V!blG+M2C>7hQiEym9t2Q1)&hEN5HZWM z!YX6O;UaI10fXgj&(Y;4Q37PD7e|^ri>(+ct}sAsCl{r3s4v*yw2`HfjUXCo^3BLZMnS~|ID%gfhfC7QQdM=w@OSbnsAv2o*8 z_YI}yBu`I2a#SUHHK|iR|J$w;6eawFifK`o9?AjW~Qwu@CRZ>9CiAdlO&BPhDA!k-S&Jky1JP+7>maUL~#bBh=)1H`B)gfp* zeC&vyjtHuVMigl&oGX5MN;x+71GE;O{@_%d98USQ4KlFm8jNM#kqUY0Yqt9Rs4DyN zuq6Xj7+G0(-Hv!oc%)go<>PIyz5(`J-Ku`SOR3O81t%>X;jWsY0xQR3^5&}7JiZF5D(&#p2@pY7bbtbn!jJ9l7LH83Q6 ze}xdV{~Pq>>OI_;W7=~$OgWdTTvTwft#I;#mvRYd&?x!xp>-p{0z=-zmsT3~v!$ug z;#&s*` z`-u1Q7Mzi*PPG%yoz2ub{ekp|Z-D-!B1k)1?yM#(_XuQG^3ZwOql*Bw|CE(10gt1C zp^zX?pO?ds8RuQO6#B5il|X^Knkv3Kvqw#$I8USAi)wF$$1t$r)lOKrS_ z|Mp^o#Gxq6L8mRBkw!xFfRUWeiR7%RPn*^#@c4TpMMmzWz9ai{9167@d3aro{B4AQ z;&TL=fP(@`nzolWf{MBzZigsyJ1>9ZEn>6z7o2tUdonFjD5^!B;{$!#D%h|Y@ggqW z*GklEsKr;{t^*#AN?Q;h7U3&%$BW zfyv?9>Uuw7Q@5oNV{ZhB^G@{CIbFVR_r3hzZL9OmL9XX$e-H{I+d{<=2kh+J6oF%2 zSV~g%8yvs~T0ZIqIca@E$mxiSKnWtLuNZ+`q)0RE&|4N?rbZo;cRe@?_~20+yRn;L zg9R|**7!h4g1iSgEiu_xAlXtD$Wi|xzZa74RQ<>J3`@sU&Zzx2GyfP_Mk&Ie)e6hvet4{ z*p9dhDNW^|G{95L#u^+p9uJW|^xR|BV|=k%=azWML@K9WKIbH_m8}AjKI%OsE~y_Q zulENhL3W_StjX7{!;rTG}a zV6%%ikEA|&wt~VId{cHGt|`58vzgb)=Pw01ZI(lSD%Ac8ky?pZf6bqWZ|+TgV7x>8 zKhD2K1JO7?{0edDuRCZ~{Jqj&&E5!=im~1Mwyjf8=orixJazfJ#oo;clilC$7JMmO zvtYDkX8Zl&--6YXQ*ifpbJp_h^zDGc>(@cp8^|Wm3GsjQC!5bB{IWa2hk>~XtyxI8 zxw!Ci%)9grf_4uR*y9@Em8J*OpxT2+V%~JiRJ7#JSARM(pKvV7d)Hfg*x{3F7ZPsJ z?5@oigFsQY%LJlILfzy*3iEMZ5n(x$!n)vX;NW)}X?>@@{*pOx@cHxHO`@+A)>?(Y z8`r1YFk~(h_Oc}P7>#P!E2w)u`zwo{h_-(eNOJGM%La7s^vxrCj9>n0(^|dXDf5wg z9z?%xMC4=T^1H`9M_arZ2BTd8pqPsS@0rzuj{PI$rJ0iKX}3i^{y8QK8^yE^Wz5hh z?^AX&)ddsb!$ko>Sx>(3=7d7h1Kw%cxp{7tC2$j=)r>H~n}*laYgV-?j^~D>FaT-| zcbitJRq$JhU9~^olsAWap!P#dl_!lYibPYNjauE6yKiAULNnitoX5?Sx}PC@bwzz- z^rZHZHqv<^=;#l<+r#Y*_X)WhI-(z053{F>i_jDgb45PFQTK#%CfDTO3pL632Y)$ayuF?>dBqOE z>zki3zu*IZbp6$TJDK6uowP0^lM{PG7YpUP2bMQ?d^EBssQ-F5YjXSHHUA0xKPJeQ zMH+zFbnb_BOb6)vLc94OGZK80FOWApi{l0bl?E005@fp)$uoImbcu50`)O zFaBJVbM{$$lV`FDQb{k^b)9Fp2`;lgi!_y2qTzwi$N;nVixW^wKVoz|O& z|2?Jtt(4{Oz=8MQfhEsiY^s06xo7{*vcCg2znbx%w!sXhF?RplzrWE<_(d*mcfFxL zcmChs|L-dIqq=OQ?_v`l>;3z8IU)xHWgu{ZcBCV3i}Q>o z{+aB+-jjFuhrj*R_k=Q=glD*2xij)K!X`v-OVQNUuU0~Ad9y$b(R2peH^@yU*#zah_mhDd*k1BU-v1ngJuKl5M? z0PWXkGzT>w#aPcp8^_P{t5drrZ=^mrnt1a%fX;8()d92u!tml>dY$j{R*48*vDb=m)4X% zNT2k}+4X$e^nnaE0!mW}%W;^=#D1j>6djAU|p~lK!kn;R(<qFO%HNF%8C1w84oUaQw{Xr7jY{YukimAq94*1+bK1s}DT+{CdzIofT0*46tUsgtV8Z^&O-td(w>L+H%NO>UHvTEqpS*mM{1O6Erj6@e$GUwM zTH8HOvA>Ld#EU=KU;ay+UmBC2{P#Yh%s*2;2Z>-<^Ic^&(pr)~Nd7t1ujT$lANe)H z|D61fyKDqBFSKEn74)OF_BjlDXpTn%Z={vy*eftr;l=Fp^DJ&W_zqmGO(Y10LimPH z-vsF8n$c9{yPWD0Ww+jcw*5Hu@-I|lBcN=6#KqGQsr+!jolg-G)B&#yu#Uh1umS)g z(E$bigvww8xA6cIP{3e-+koPqDe_C6e2V;1(O)C~gIfR%xiS@==76X1%l%hAU;zJX zbi9}Y^dA(rvaFTY{C5w4(rBP^2ma^|U>$jU`uuntJnEl%ia)ZlR|W&%eJ!}i*CYHq z5V%_YD+D0;^LOpPP#Gkjomqgzjk*=_004rS`(u#U|80xM_D34?n@|DeSG99fSJwP5 zt{EgeAT<&JW?2&X6*&_-g^=0 zy|(}Xq)CxpM5zJ-3ZWyQ6crGVpaB5^0qM;z-g~|8tHxLF`u}fzS!X5Z%-Q?dd!Cuu zGjq5D>O~|Eh>i_;l6JjN?-o5rqm7l?ZfS-f`6fZqyu)nAJXT`sz zgkAbc_!1yal{52u@BZnCkU1InBS&P^u^l!!Y!X8mA}NFs`eAtlOzDhGQ17Y za;NzR>wiCmkq`hDI|Trc{8I`1B7q%K4Z;0|@Gp|FFcE@vcI{=vwSm|qp0Mq4eJ)z^ z=T0><^8dd6f~l0zP3C7pbRJHZlb{H%j5N6WKZws4=cmqEV{pNw{%>7OHH1PQD##oH z1OP4ps8j$%kYk5Sgf!+~V?O2$BOyNs|Lp4b0+^c2uPuJB`^_tig#5y1%m`>)Tx+QAq@2qC&m zMo$Z?caU}H{`8wyKic}QlNe(NHenOp;jM>rXMwfKu2jD)aL{maB}bMbG?WQ>HU{xa_vJ)yu%ED&Ka#r&7LjhW8qP z;=UWphP7^}Z81g!^k5QG4Z&8ZI1dhgj*~T`dH)TOkIE~#nF~B0lBa&<9&Oo^j+$VT+FJf^+Ngh#sD~KQc!PsQ}5(a#gS4DsSYv-@@@9knDojD(P$vh2%;r~hdLz(@$TctWZ@dz$t)L*HlrXRk03LYBjQ*?3p( z#Oe=0FcE@nEIdKv$cT6FI|u&b5+*_b?Bi@i+_@^M*=K;w-2`2;CDb#QQKNsRJQhG7Q5Fj%E3qbV?m7l1_#TZlpKl%2P z;&(a4R6}ro8;ZZj#7M~AdybXU1$Oguyo^?UmsPF4SNYC|uct6J85uqkDpcOw(WTKe znRlEyke{@E;0jZd0bFVra81U=5xPgAh|sZ%~*B!Qy%7KSctbS^h&1 zOoRYdJ$vqYzR&n0Hqg#stRc9Xib2uMQjk9d!9)nQ7H9T#&TP3q%nL3iLI4zB>0~d^o0J9ho03cNK&w0T-xue2p?$?Q!nhfr5oc|FG6Cqe)&;6Rp z`PTmw3L_!1w!!Q5yez0c1;JE9@GBrf^kqv~za#TorZ5qL{W@voqiz46x`Dog2>j7p zGJrGNo_*|_mES{QY%)K={xc5d7$W!e#>Ss-7@JI(Xz`yTq^MzxA*>Ox|AQMT7zrVy zJ^f$uf{_rwrO^K+FYFizq55CkK;QgJ2L71$WB@N?oDosx{TXrn4Eft)36=hBLQ<-z zU-|~XG;}8&yoK*Ax%zYv&LyYyfIwJWRpw)u#E-WA!o<{MC~+?VF1agNhX9zdNti>3 zLI7CI5C0*9n3@dkUnc&=Oep&MpJw8i2>DwF5n})AEc^@qt2vA@1Pk!Z6P(xomHdYt zOoW^fF0H-V=@R2?9hCkJ?VtR?Lcxy7Qk_tO;X zb>JU>U?c=RT7KOb0~jUyNchdxKSE(5gn(QGwK=XH{b1?6?Q416Br~4mnVJNbaH|Rx zJZbXEpXkLz2%zF(N`shpv)O|b+-Wy@%ZCQD`hzden;pJ3S00GH^^oT(=adDPxa-OQF7<#yCJPy4?_|gJ}2?UUgp@y(V;sQF=0IEP{uH=rC zOP7Sv*Nej9Lgde|eqS{I0mRtt{sfE3`d{URkr3>EnM*Y)4mZTMA+>l%P@JO1GEdT} zylRCJ4I?4{mh3*ydPw^ue(Ca51-ch-7oxL_^8L&D-_S4;@^49IY;+L7Vy9BE{wmK_ z0boN2|I5R_ssBsz4+x3JE<|gE)LW&{p?*~V7bZqR(32_*pAZ1{B@D^vB#bd61hed~ zQZdDlzjeD9o&PZrV^ICyZV#i&1@I%R+OK^6W%~a$LYRSq=-VK_wEN=;LQFA46-O5Ety@S@Q@WaeCA{ zeuIXY5VR5=*Tb!171mp}a|UL=!T1FsXf1}~)`R?t&;8O3g1^D|b(0|kkyzJgQp+tO zS$>CsnGo`3bbZAFhJ+FVCgtw^4g)hGSb`TW{Z8|*^S>Zu9d7oQ%y0KF*AQwotKVw= zC4iX_K!h&#vzcV52zAjpWgLf?zvMCPVI~AEiGKI!hPotfNQbbW=pH7`ztVm|2wFfe z?%=_2+ewPTaClS4UkaG^FcX57q{>z#!U5pMF%$yLezUsb7lZ%+B&&k)m31#hh=U-Q zZ2vv&mxKTYieBrj(vPQHRxta!0*3ux6Eg8aQv?5bONMfN2L`?Gl72}D_E;$H2s?fl zGXVUZ0)~TM67t_(;=el>wEvxikr3d&`|dye#@NeHRDk+sp8)HvcMmSDCXYw9NQJ^~ zKD|Wy2`36z13BQn&6suaM#C`-^(;jV2vU58jcH(3Y;#7-Ww@km;Uir|6p-0dM_u}I z%>AqT2+9mHJR%pb<2~_i^MFvqWN=92C0o^y(o} z0~TscDmfXxA$cWh8*yBaa^c}D2#UAET){6cQG=Dm6fgDs~7V;A<`vF$Pt9@pX4<=#hz4-*X6}NY?OoQ*TT)1R%o? zAWZJeYLyGcI#|WMXYkVq;rnt|#YBjr8VCz;NAymmZx<4Pt?&80irPSpvK;fdHa|5 ze<}XmJ@WO@P77sKZH&Cs+EcYUHP-xH9@9RWmy`B@g-`hyNeO=NwS=;YF=_tIC%LJA zAFyI#gfjN)$td980ak1*94rD{Y#gkAb(UC^EJAV=dgkuTf^MPkf?8cO z#K!36rI7jLd+3K=3DL4xvJ{1JJX{YK{_j3-`v(v60^>ltMrR~89{c0lxkN17T^H6Y zTF<8E1AP|ez!i&EeFlL`CAhUl)fuIh&W5a^!At$hP**rXE|I;h(LrE)3`3fOfw%JCfe@{8i_1nb2|j% zLFw8gsGiS{e>lfSOyo#0vKB-ZCmKpTr5@qPrQ#1RopD4EJ1Him(BP;9cG+$Sf+lmV zQ*@pCvK-&U!5_?MEbU(y9i5ytrfmq*?r0S9BIj=!S6Y5wG^CT5^EMv;ltRG1@L0fD zR}R;UtrnL;?*I8FbFPxNZt&MzR9Of55jhoySlW(>k*&*~H%`b+gYK}oagealxE{wE z#5L01dc}#K`3R~GhN@MEw$eczc>}`~7ZU6I_;`?T<@pAxEN;J(p~LcJiiRzwZRx<% z9$q1R578Z2xJb+=Et;|*d`{^&9&>sxN=khuje87v;ZWh)RtFg=QYwyAkLz?_0P8(O zk7Q*Z=PO6TXo=4)QZ z*^P@DDJ3GZ*SE!}rz|(l*Qr|EC^};j%+_NPAsA;LrP)ePD(49%T00I}47`~M+qf`h zmCqWb@yW`KIGF9a&S}uo6JiLc(yTSJ;F*Uh`bE?_0}G7l<795OAh;WmlWoA+g!=OR zb5tHS-auTR>OGN_TvjVooHkr`L=^q6=Cx+w*MjD`3dPr+`ziM2o-PI#KiX#?ACvv| z7~vyRoU&f%{b;tCb%WT^oXd=EQEEQ%S~H_LwYwLDlMw~hjULIlAbJ$LtAYb_ShuD> zwLPg_#JEty%_Ia^nNcp0!c~hg1Qc$#Quaow0h;+pUxNds3^8;N&g(?-D)vn}rHJWv zy=K?lVp)%GZWJQ%kMc-hPM24fy#pFzR4`=p6vwgi0cmI`72S}Ze9Xd2Z6_@!1uUSy z3@)C)mN=WOJgdU`T+=jV8I@)e6`8_lLJDl*tAC-C5VguXSwbAX&N|!cg5NM~hB7kd zi+s~{W3RMtREMP@=fp@wbs=cmg2_W*EtKUNnfsEk;pbXgYgw)VNcsAcr8^DgZ}k}k z$L^l-!m41hOt|m}>0*m}n7U|n^*~S`cHEyi<8-x4?y_E!y)6M#IOk)c2QN?YbE6Ny zafdeZgg#)$}lX z(^VUO3}*%t$FRQ>|IBLXUTZ`ORGpr(?c3+_RBTI2YJw50NHzKS(84c!XVr%c86QX) z7QGSO>D7Yi+u)y{QCJc-3ZQf(eUg|O2AT8|jvrC?5y5lKcC%44A)dcCH-i5;sE1N* zI#fSDV@t|${pc(+Ki-E`777R1J=WVJk8>!u<*)TBjGXkU%DiYEk1Z$;G!?OA{*FpHJh{-* zonr+kFeO|iHe|-Bmrod~oRP#z)shuC2 zt20b*m@H?PZf5e;T1D%4L`*ZiS3;`H3uUKn-+c3W-!A}cO|8|*w|y;sD4*$pI^iUN zlwy^EW?#1(z7u2AuIp+=bn=p^Ldurw$K*G?!AN~;vmMpZ$S23gq~iT3S9cxb$Geu> zdO>)c!Rw07RvI(|PB81(3s3P2r4Xyl{^#!ciYemRGpcD5wIDeVi2P zChk9KnWw3p&I4R+%tjW?Ky3Tx@Npvf3O?C%zH=LhiuPClf-(hi{KCV}ZD|#blDjNH z(iu*K7Fvgjo2R0^fu4r5LZrPBZ?s9t)!Jpar?gwj}T8{q+{AfFQEi5o1 zQ;7*5TI$OK8rN$jL-xH0Mh%Ye=D##$4wgK{NAy7D-NLPQGWsV6bhPE(K)7@|?1S*L z6&=AGp1b_wq3o|wH?l}Y-9KHXKOq|`1ZIVKuFyqwr~N%nUURp36wlJ{@lEj*It zGE_}(9gB`TBAFWM_;^<_##*4_*#@KMK3~cz1nCYbWA4w`jv96^O$Tbi!aMq#nB0qB zJ!;P!5BN;C1I{4<>Tk%r9lO#kf_|wn%4(w3h|y4dR4equO}el+CVC&K*hNxeFh@{{ zR?jFBA-BP^I+AVa&h1Sv#3sZw%iw93nZjB+hqFK$7@s0Siw-~qB{nJxZp}}%`$sI2 zRb31h3A5cic(e+r^WH0d0YrRW_tb71Q!u^vX|Adgg^-gvb4(r7G-G5lMA)kw$ZB{X zry-%~%ErgF3xVgGyQp5g;V?14m5!`pZodYj*&85r-hvM1BSn>HOf=Or-i%#89K8O< z$uK_O^N!x0Ji~j-vaO=hgQEP@B&dN-ib_?QFBMI>p73jtl7J2dhygpgP7Wq~nRuDlo-7&H9b?t&V7KUkh zS*z^<{u%ZBCtRkt56(Qgxkq)bRO^Xi{`D-k45Y357eLYL#x>A2iILWz8Q&=pKdJ5O zS87X|YM&+-_9nV&5z|AOM`_!98reF*Gz)IhV5E-#K8`cVxK8a<$XMj0+Lm}sM59x} zQ>82)eiA>Oq%9VX$!q!xK#G3U@|ODrdaXUekB+q;-MNY+uED57v(tO7RFO(vSPhip zc}O!sT_ULVOEK~fb9DNZCY9J3h`+wtj2%?HJK4EbDi+#@qu3T3;W3hCEFewO6HyJpQkwKH zN)GQ-An0T~C(eTO>ljyW7EiT`ZZI7NQPRR~v3)ndiNLg|C{Y2H_GIbt7HMS;EqYE^ zMhf!AiA1b{_}N#PVOOp3x!tyTo1RcT1jFbk;dE`w(bWZxZ@JwL@pnc1pC~Bw(3Bt? z%%yK0Q*cV%*wDy1FT35brRmKm1UifsK3yO^^x-=W4ksX}Ze3z8*WzTuZ&#KXbPPTi z7vp>L1&~6OXOHbI?1MPX90o44ym10+?gaF{7aOTd$U{IG4MnO4KB`)N#*1I2dU*KM zil>2H#g3Dz7&5JcJm_IMKV$dk{f0S0Nh*4B;3=YFG?x~N&>r02bj3NSyF6jNPc@-z z6D`p(aSaFZ>9rMrEHmJ{sS*_p*^L=?O<=0OREbjS)ZSiNw+k9_{+%^RzJm8wW6{o|27> zjjNfhwUYers2V&QjJq!SB}}cUW}j#Y@a@wjSSQvKX-NmZk|J<8n|6C?M!MQ_6KJ?? zlOlhsC7jBiP@@c=1KFo#EU_yVfG-|Ec6YP%UDdONw@=GI&j7(sf%#yiM@R>rR62`N z2EC}{SD@TD1$Jnv)1mwP1#qRmh2N5Lmfx8dI1T7mLS8x|)o<1ow@E5PX;qPQ7f44< zOJ9(dwjMgg{opUtle^Fq1!zt6{h3(H#C~(5RSsx0~Y|)_fdwuOj}% zzzB_@uoq`D6%T!Ij6WBZFQ{Wg;39e1+&nOsw{L(_ z)OcuXHQyYX;+`!kz6iO5dsoCi6%lo-Zp?^7D%uyw@mw*^!fB_0Dl_H%OOIM}f$=Oi zGf-r;+uKX_T7WI7SYhwLzQia}F%Eipc4hL=s*?oT4||{w;pLpyS_+fAFBP$R&mQm_ zHWAb=jB*LRPv$ss)$ z^Wfy~9_1;VU3aR-p5NoJ9$p!#i>wgoPZR6BnFdZyUgs^iPkh~ShhzC`pi3w1B)1aJ zYfTDuF5q_Jg-w$#Ia&;p8k3F%;6I}86iYC4Qf;elya9i)q7N#K?L(K%rz)epZ1j6Y znQI@`-p-rZ{ct^Yy=mNV7s9{^F}|Jm&V5Z&yF$msU;hgrPG^-9@_EmQGqR+)mn~ z6E@MVtTuP$&yJ)?V{`C($n<+^W@zn#B7H|AB#LMT!#2li?MVwtQ>=pNPpMv`e1CqmCkKiL>@@2&hP(g-}F^%VCG|1ru}zCW5`0ygC%6exw1P;d3vqhmSz^56KH^NxlT<(k`dHX} zWY`Wi^~AbLhUtyH36s90VD4y&cm7Kc7`?}hrN|}4+%IbCnBRZeHg_A9b2~GaefKzc z>j_G&QAfc~!x&m8RTcX&a;|_g)io5^tySE&UG}0nzE?LpnCLA*0jt7wK_Tuw;tlI8 zn!aoq7q2ZA=gZ2tnv-J;7bZFzwv2@ga+AjbNRDbj-SjR#U^7b2b-Lo%^Fa0$@r?&& zQx{j;==;6^2r@Tp53Ll!K$&NpTv^5HWEi?^?$!0K<3A*klrzk1_ml?CO~4;fwCb$m zMNRT^wnpx;Ehjw&x*sQToASS(`sC-zL>1;UwI{L`oT9dTAR>u(l6Ly^5*K@p9en;%KtlEfxpglCMKN8M)(Q0S8EG?RZD5K&|t z&DOOkfJknH^lLp4I5@+pC7M(ad6+)?1>nU`&V}VFjw~L?ynHsSBbQgA9cR{yDoz>h1-Wz5TO(r%Ea@2W z`2xUkU1gI>RB!AFk$7rqzR?`66EN5T)SK~ZOdpD#Mo-Hp5Lq@rIkC4vAStr5jyUg4 zNYol5#$PMnW!yU>v`7Ta$3FL3UmfYf`XDBG*)DHg88k0dx?$IZ8-d)MY}Q<4RP}%+ z5X5dg^e@Xl?7d@wlFkhqb?jqRmrRH_>%{UhvS2-_Rxwezr#eDSenz%3P_TKgq~WP) z{{Y7g-Ju2iOs;HsE8!iS=NkwGgY8=*k2YfKfZCSAdWaY9br<#-Z}y-Eqh#xv>B^bp zXO;CQUCLFTe*pm31|&Y7M~+^c^c91+d1q_PS0^1dZ1d?!%v{KqX{zOsYTGoF#)t}jd340}qtI3X z5>GO-Iclj~kUz0dM(dy+%6Q}hfIdj#K`z}}+3Xhu)J=pAi>`)*$Vc@g(tMLD6`hlKmKBepj}QGKmJM6AN= z=aXA$wQW(S6Rr`OqrlSRaOgv`mba|Oq^)n2Vt9$kkL64z-yA1SKJu>Q)^|P5bhH>) zB+4#>i+{lOM2Tt}-oDy|l2K4o>ah(wmM62-{?% z^bt9oSicTFA6tq<;k@Vj!u_*DS((S9T;9zr^f|m@r1s*YwycaJh!y?`|{Fk=oQUmj0LokF4&?=Ei;$X zewa12=0O=~{t^21bgGfa3P(GaN)Kn2d5T=88C!yxO2q1ik%&}kCvEf9RSp_0v97sJ zc7AL>Rmd|c*~iGk-=g+dhb3f&2JQ64w;hV(RVo%&Og-4uyG@hEO zBuQp00gq%^HDbu<*lo02p^p>RdK+)vF|lrzIHDfTv7kmc^b01xJ z?c6l8m~BXdk2TIMuEaq(2X2N+;4KEsrG(d0DD>+sR0eH(C97V!6l6- zXZ-hPZaS&oQl9I4=&J2%ihua&w9YB<80t_fPjpI8;Y9H$Plb3sUvO60l;xoe{gRr% z;q&NP9)>}^J$iQNIJLG}@V zY+XORER?GyNo*!(R-4L9h=W)wupG=EYq$eO4{w?CdNmhg1)VOCYG#B-Xx2LU@8jOsrF0UJA4xU*2D-ZuvfS)0XJ10aCf|jLt+GYLU8hhUp47xY ztrUAD%c{bIB4K>Q{G@+k5TsMSPj^Pf{IW9AP~6PNyp6L@=VM`~)&bpHHvV_y88r41 zZ0?Ro>fLnFG0!w#h)Rx3USN_;@1fLoUT0rjTBqoGKpv2^b)fyQWJQ396x7bVtHc;Y z!g{w%aIBd!8|lY(&jp_-)v`nVV()!KMrP%sN%bXP2cm51D_f!+lf_z;@$Gn0utoB- z^dVzlD-~tj?)^1nD)PDNb!xplHihC(@^4ir<-PJdro6gPHK|Pzm;0t=2b#RPyJl|W zl?`z{b?SyC+SMo=N#mY62PtZK7t#f(h|QhCN+Eu_b29#5PWGk^mj?D5EBWLK+6eOx zWI=j`NZyK$>20Cn(FUms#4V*NCN8@ZY|pF(GG(}yZrp^XdWjE3HjjW5tTWi4i&*~U zz5`cb=RA9{Y@x+v4u%BQ(2^nR4xTagey@(ZJvJDT`RX;%+$oUi-*?Z3V=}URD zy#*w9D>7JBZ!ky^+xaq%ix)`U(QBmZM`~vpzE7#LcJH!E-r_TbKTKFh-1pSMwkGBp zgX(8f)fheLYa>m8P9A{L%_})VA7S++xdp3Q=zH5rZiw zBWs^CapFr%!e^G$li}wJPf;3bu&aI8R~0V%$4;Qc^W8ExKx`A41^d)5+*!SpGoDtM zwB@wk#$E#A)yQQUd}4U2;3SUV#WC|gBUzKxngnih2*gcHZ(v^}t?9*=;et^3fDf$( zZYgqVbnNze`4RNC5noQ}aNClJA~cdoGM6c%Rpv&=<0y+KD4zpXGZWcR8a~ZHTwm{O zCq`WjY?YH2PwVdP+A_XQliH5c&I?R*tw|fLw!a`bZcM|#I-$0@G|KmRbYWtQM{E1t zIfeeT3AJq38Q*>OFMxf(p(9Ci;b64SD*w6;%cF(ZMD5cVzn78XcJcTNPIBy114<#( zAd6HB$&ePiNAbAoju!F2n7gVE%-Ncen|cjSJ}jJD!{8HRUOG9q0RiNEPf|)iFsHhN z_?=pB+w&c-WT3W6)zh%`*etQYdG4$;4yD;tfy->1>v1;87Gq;Od9~@<|lxF!-?`sF)*)>~a<+-s-C|~w)Ys?(K zp$x%h|FkyT1wn!lAiV{u!9{&-1m~-Xnc0}#LdFjU?%0riLx_>WOs_g@BKYun?>vcu z!VO+!W3j5(QZlla-prhkYb!%7=#jNU%pI6r{WwC_rJc1zGX-gF=gcA}2D0;gOUP}? zLh+^}YPqh`+{$i?H_>QvT}hN)&``XfDyaJE@EtqDj#0CkCy@g^8y+W5Ua-gdmsT6$ zj=(O`%+;m4KB+;Wj2KVi$&@RuzK}kf7_6kmM=nW2dZg#+J6C&Q*Pb+}w$a8bg?P}5 zij?k2X&NHR?xgsBMAZ0<5s3K^wjvF?%BP?=<7m=Lco&H3K6x9FCW!Lig|a_{$A98p zz3mdTEpHkMTQNF5JB{6?&auOI)xd74S2m1ip5=ay&Xx^*+O0H7KH8c_Ev9QjJ!^5& z1stAhT-kdPyYwyeqK)YP0WW!Is0FK_bP>9+Lm8=bOm5WR`1k=ja-TsQQRO`CL>e0) zlBd*?2;9J%vi(~td!z=oCcXA^Z1dK0s8rs{BeJEr)6A{h!t(3%?M(*?h0a22X|oiw z)}jZXha5Do=MK#|*Ql;#UpZO4dtIR)W%VScyZ>lQ+S_!N_!WWWL)=XQw~O~vaD%#( zG-sj6nKa959v@yWfhuGzIw|u;`X zvo87bVC8F}>?X@d&Cx>AqEJtB&n@V5XsQcgLk7MxF_P^H&76XsKi{}Z602?#1AhIh z7U$8d1}T%si0O$fb~tl={opCF@t&5R3U|1vnVpbO3td~|8kKMS7I$Dwxb9PuDwf5W z#3>V~b-ne`5Sz0Ihs3!wiCujQH@-*FwN2zDdsG^x_|Jy}rU%QTYUyG{8E8f4Fj-SwPG4XcWE)j&c8#YWDpeRcABGOKY*hLJ+ZSPKtRPXO2 zwV>LZj)>2p6X`rAtryv-h(DT~4!<(F>C#j3P8cuSLtGbm(rGQzxqrj`V%x&D!gcc& zv86QU*d-_Su~L$KPW%rz4MwauXIsyz%-oKU(IUI=7(iN?6Hm@jjbncw&cDbTql~^d z-4IRfDuNuR5ea~$QsRG*8;7xG=ItJ2GKRlyyVIJ1&FA*~!;5_;U`#gKguzkVsw>jv zjA*>^)KO+Z%Ms~5Q@2~T(3{jn35MMRn8EJc(1Gmd4d<33N={jGaa?$qqTY)Qo8I@U zke9>?1ASWug-CHN(+&?w{Nl-nEZ2a?(H8G5&*->la88iGvAfUSw+$BImOM*Fq)$Gh9Z%0Hwe35nDl`8fsK=j5L%tI|1Bx3* z4DWN^p^<;V3=h2bM%O}Zpk#3_iri2zf;$?LQZ}h!p7PRh-7n}^$d7P5#+rK)#;<5` zRx_W(9JO`LuD0mzXo~NdN++k2daKr~;sP|oy{N6?Ap35>vCK)tLYqKT**J1*6p0Szu3be{AGu+-coA z`s2(`^zOP@`b8Hnd;zdlz%B;D4&>|XR88}@tOk&mm+h>^cc|>IMm%h=D!215mmOk{ z4j1XMnY^R+1h!W}njgw*ikGL9Lt3pR2y|>tC1dEc=Sq!y2Cv&-QA+?cgmzqu^?}Lna`*OR_wGAV8Tl&vbu9S=eY`waOAZq!b7>pvTUeJ zVM__)*~h)3FmI4D(9}TCs)r!4?JVRbjDckhRb1u5&_&<*I)Sf13nY~%L*hXN0!OZq z2;5@qnB{*znPX=rK(GZNc_!N*Y-oz?WeBLZJAA{uS*0WKjN@b9hScCmy#Hs@OoxWZ zL%{e=D~74%r7|BHexgI5;yyIRpDx_;icsmmQ<4@Z!;u_CcD<3Ea8~Df{*RQR@Z(;0 zx=^3D8IQ;ZPUI|Cs8D^q$(qQr=x){sZJKBR~xTLReR@& z5o2UgM=K+KEAT8RE^4bMv}4_ALMvXNAhKyyrrb-QZf)I{+?H*wRwYhKB%P0CCy?ez zX+@p5e&ys5h1DRab2ordZLKYpSBH2ft;YDGl*05#APHlE6Y%}XswPFl>@!W@j&zq^ zJAWAm)ss@%j%GT+NvV^Fd(WcYm6XG?QuxCsH-|GVxglI|r|``zjreTXT#VDH_OWJMs-g-D=A$ z*>5J)8Hm4T5-en5-e8xx*K=@=)4m~43rt)zvd!mdM3)0ZeNudok~uxL6kQ>-rGhuI zkitf>H_AP~f;C@eUMZGqS2v_ol+H{0kz6_4m_BI>XI;(=I>^~Ro8+{rxEs(Z_Rh^P zqE3md4^mLPFD7DK^N7rBxeT=8sebUm$Cg2?w5vZNIwOTX&wL+ zH9(Iy-(z)Hhm=WBV}rMRU?2El#FJ>u#VYZo2FJ*2I@y~P+jcVYU2na{l-bLP6D@V>#n>tlc1Ip5f*f|wc^!%cZ zV|v6!W~0JTP*;E2GV*a5d~azpHPfT7K*}@g3C&XSz{KjV*pqzhSq?Wx@nX=xFq7h@ zN``bk+jG3cmSyFZoBH{$!Qn`Vk^IyE{y>yar^Iev3vYwJ{22KKUQcZu0`Wpn!NU7D zexeMKlTjE+ z9JIM~94G4JkG7IY|F?aprx{CV?VHD6iI=OoMqfqqHRf{GvOOr5*XSs9-=(S84N9H@) zB9=pU*Wo#h|mRfmY zp;sc6l47+%jZ}Z8_=Z#*$7U1(oMeAkctk1;JD0pc>aKLf`xvNoIvF&iWM$0grCqDG zR{fe{(FngZ>X2!Pe4F49=LG9CC+)6)FupW8-bYtt%R&J{I@CTB>Q;QfLYsmVxy`G*+Eo zlaO`$!d@||NB2Jp$bENBqU8SMRFRv9S($mpOo8Fee9Gp1(k0u+WiP|J`gdjS-frd( zzYe`<(bG##4<^VhkyP&u_YPDi##x-$r4)MhT*Xl$sb=fy4ojvZuk(J>5?|nl$IrO# zebrQ_F%boc)m*P#bLS_#W=~8qphJ0APRvea1Is~1rOdoaQWLhf2R&qt${O%Lh9^O+vbY4A#cVx6oj9bK^m#GTZwWj^SV$%Q1t62kQnju@R-`4Zh zz4A}g)Bh_J{3jy(@FUjy^!@Uk+SUls&nc_W)R$<%Z*+-}7wR2d_EjRV@Ed(M|wy9dzc9a6btMNp=RdgiN zEB4QbJ6;K-8y?Ba%{qs#746g`%JJ+d#(ejP+P!fkUi_ly8PxDeDqewcesKFr5^hZB zo+s{LNRLkU`w{>3{#3**+2_GX=rR#}m#lGQA2s=Iv}jTprLoVf>Uf~Xe?IUTkseK_ zRW0+nsfp6Xkeicv38qvxj*?hUs~X?-Wz6VZSos2w{sIWw(pJgco~Zv&n#8K+SZpl5 zTIIN-6{LC6mm8$_txygi&9k&yfvL08j-2c$f2zkfm^e9;Drb?-EJg;?(yRg9tDtft zu!Z{MzFjA~O};s2+PUgxSO%QSLafG`2VMp5Pp5oQ-Yg<-?-UsMl5tEpM`cJ|?D=Rx z8qQ^fuCTR9wdC~6;+|Hmti%$E4-03>d9bxA*}B1TFst~~yR>W*?@7t*i<%o?X_e!` zww4kbzO)qk!cxGJhndN~6F5H3#1{Qp(8b<24C0ns(abHh^CprZQ*>ko- zRs$=#!3ORA$5~juES&RA-O7WZ*Zc=s7EcCUhpR*OQhbCoTy&aOwvJR&=smA%O%A57 zo%EEs;~r4yv>mam-?h8Fncp4hgi5-6%;?A@^h$zoe26>4_mKR?J~wQl{|Y6C%B_OcVo&6nbuIunEYPp1+8s|(~hMUqq>%$oSJTXXfg@JW=;Yg*|~GZjs$92Y4cX$Qm88v7<=k7X>YfuBX^ zk}^Z&X^+BjGdI@@>22YU7mp}sUHk831oy`pbU)e-!2c{+eqQYaaaRON&Va1k>OQn^ z77$49&!`10oY0H7y-}$$9`@ddDOpg~Jm`3;92@_R+QgIv-f1;vNqeUDfmEOt|F)WJ z;+0Dg5BB5_1<5oW}%nIRBt!B3Kld&Nu89e}w$^yRrOkS0a94 z_o;o#IbgMY@}^FZrY0~o96q&0BRaJuOq_OC=_Z%qUMY7L`oGkB5nB zeH#)QaK65dM8>GhFoWi~_1^pe@Z>HP6d6%@aAwzgk3q~%wW&-dTqp&CtvK87CELGq zu5*jdgpc*cSt*gvlpMzStirUHor%Pyg>7%ET)8LmmLzI}q4gciPnoAv^r+|zR1}mV zw8X99u4LyMh#qM`^P9UGAl8<=?++;NFNA*3XJYZd%5e5M0B0|x#o6>xcO{aIpmxhX z%WwwtmLHvZAAql;FB9Gn!YW1or;Rdjo!v94kUqC&X8~_%c+W<3p}w6~(T!Yz@d<$! zTStw%{MFgMh~{=7wI?4&3DMYLH83Gp_m_ary{mOs9oHexZ=3;@ zqF0<_6~;~Gj(n#|TTye?YH zC8kkRuS^5B*?4APH>aUoJFYw}UrX&`wMxrrB&*{JMA=1P;2h zf8SvH(}-_TYrZ+ho)Puv0exymAWN(N8MktW)i^8tyk%3ric9U2k9+Lyh!lm*21MSR zm4)kkIs%&XSdOUN(Mz#!l(Kx|SrKP$u~5!KJI~@sU&?N^dZDmSg3&;Wtz>ZWio$Ef z^}c&*^*r6aVEQzdG6EvH0?{xgM$M6NPCI*Yr|`h;mtxTww0Iq&Dd^y_6g$YSPoocp|u~vCQAEx4T5Lr(w8tkQE z#;53c%$#b*d*5BD?NM1`#bd{Fn+2(!85>XK5t1+9$ot`AkO69O0V!{=hBE!>_yzE; z$SCci6EXL~`&yS|TBdqY^ShUu=F~IxBXW6jJ+8`AK7H*Rhq0?h2TETQcCGEbGObOrlq% zyXUd4-m-AX4}^_ERMTki9XOMBb5d0stz3h;8k6)WA1;XY7ti2UzGfaMO{t#4zvj8! zN=oyDkpvf6qfH3!pM-Qw_9w$C*UqRn&0I|lfkDiZD>cHFi*L0<0Mnk`{ib8|u|{Uj z0xXglwFb!gTbd3}RJHFwPwLpouN~5yvgG(jYEnFtCPMmaI^&4P0SrC)5RPs_ituQBcEvf|)nYsncZ9-1@OUH|cSFS#QIwy`+Jj8e1 zoQ~?%=?criyG=^1W!q7hn$p`787o%ZocoMj!N54lK=64NmfgUda~2|V=8*yCwx~oTAP}_}pXQwDw9jo54 z#0tI3P%ulex35#GDt#Wiq$t1BZZ&oLY+~=H9fBGS^kAoMi%#tD#Z183tAiy?rdQ`@ z_4tWK3hy=L7o;2on{$0uOjYLBvF*(&0p}uNRk}~ne}?Kcx)k0+F@hT1Br-01A!Tux z-~sioxIx-tz~rioy}Z3K5w3~2*IfJBgG!csWoWs-=G<7f_U#So5tOg}TNo$2#f$%R zZ%KRCajCn#foAZ*xb>3D^&ZLryRZ5!BVAGT*g(npW(?@^jhB21v_3a1-hT%xbqPSkI& z_Kq(|CXNitVrLF1GLVF%Ns4LdEu7x$*VzG8#D~1Iab53|42iF4eDGjjjJK&hW?6D` zhXDeW#dTwqw`anNB9jQWZR;D_jyOPUp{ksNMi1yYt*LB!4;ef{)-dqD3|6p< z(pOGD$Y-g1I(F3lq10ANuU;qqvtX-!Q~0Gpu|Dsjb>o24lT<;SdenKZ{24m7JT33! z!~vE3Nz!KNSkODDsV{5a?StedK~qA$vVsZEiT?cLVbGaJfpIbRG`Y)5JL(6?Y2%V) zC-YpHp&aDj(co#v;>*S5OE+9*pFA*ZV?*Lf}A*HMryT-O%|ktTk2_ z4|}qCyhvclq|Hzi%9go~zk8S_<=nMNUs^0y&f@qtkaJWcnUMoRWGqE4Fajqt6&vRObAn$DrUVjW~iVFGfQC|BQ=29!+Pyr z4;FwXr_{FCGn#qjT?Fv@U+GG5u`?}#KepR&jGnKy5a^3P#x0GJ_rI|VQCo8@)~GV+ zZPDq>^`3Z9FTrYfOfEC7_UTR3@V3Jjz@{@#e3kr*C+aFgHA=BLR^VRlwZUVt$}?4G0I$23xqR~f4|i`J71z@(3O3e2 z;|(-UaEIVdf;$9v2=4Cg(zrVWcXubaL(t#^2p&90&^&(M_tsr+X1zOe?_2ZNtoq}e zQ)ic)eQNKj+O-8bM-cR)vdWtz{3z}azO3pbj5+t zDn#_@n=sWE1-Lh+m?%5<{-&sL4#*F(t(;Py2;A9=jw zuR}u3Lp+jD13?rA`w!=5G4%BUD+_}D9UnF6pu!eOn7+|WH#4pmL8$Pi!!1T!FG&2+ zrsS{;yKwZU2z{Y5m%HG_l`q%_P16s`WSNl*&JZ2dr(gKi1XeBnxq9%$uht6r+g|_^ zA=URMFwGBG^OgElyFUZvIu+x{Swl1tc=(bvs<=QruDl+YH z{x9HC=yWQQ+L7Cf9WPw0qZTCR;{(1;Ne;KVWXcN`T}BKY4aaIt+OvO8bCuMT3{Mq` z$1-4p(Lo}a*wmE7r}RLhmFwzh9+ooNZ`(YAxb2uQUbf+c=TuI_n$boxMkT%ADqYne zUD2EF5^~(Pg8lyX*Gg*m)WfGEhCTEW=BxuyRXl=M*zKrnu)V7@Z4NKa(bO!r*kaKG zBs|WQ(i3EjdLI(}DeQIVI=nh&tzEW{O`$;IwbhtZDQ=3o)9MA8{!H-oz)lFbF!%^L zyIAz}8J8FqHL{eOe}`G<`IWP#(6?c?RPHIsat8h86YFJOGvTDzfY|Y0a;+o1W%_k&n!;HGr%0*jH>$h;$cxu$+cuUMoj?F?5^m%!{+!k#_lFvR@8dgB0*T(^60DLtF8%vGYn$2;%}TaS24-kf1B8CNO*!d@vJ^1~+S@)a^Gxs2-dlh@rHmXc!YS)FH@zGBRU|JVX3X^YL^z#7+ zlH6JN`%&xopJ*f(4@1cZP!dG4HE?-*gq2=4&c}`zeM@9 z`HM}@D@c9G57{z8$hi4{1>)7(X+TDEHNO8CNOXl+QmY6){otFE_ufRJU|({fy^NwG?dSGIx& zNxuOfnYO=@--&BOMpiLEmlViQnjWws@SSVtj4TMX1Ul~@y}$WK9s zg?xONzKARH>|bWB@hE>HCRk?Dycbjcs?YX5%-@V^p7D&;-s`Iiyp{&m8d}JrH3!aJ zumf(8#B^QzC>>{GQ5e3lZ>$R0o z{!;G6hHu_%2kUJvYygNLW>~C$dY)F2EBm>B zK)rJQ6iH1>LfAYvy(dctZQAq2zy4*SS%wKch$g(_N@1Qm^fOMdYtzQDX@C0q@NpXA zvSFKasn_sozpLG*>e)s zgQ(_SvWhJ9Z*|j9*|V3h-}ifTfhk!wXHrG|8&dw&mwkDyd05C8v@dKJ55Dn%?`8`x z@MgZc%G>bGX8FILPFz=g#EIv65r5min$PV01(4Sn`5O;LJrDaw?=eVjs~rz+M+)S* zAn8TEd|>zD4{%~8{g!b1&Ehwabj!PGB;fk-d1SlgIO1<)d3T(azHIj|3Wl>KQ#9V9 zvJVvMwc-n6dK5A%{hwT$zC=>j4dp$gM&CxgAPqnEv~y$0VYpXN7X>`)NtL7ih>$A0 zW>z(((xo!~OwL~}A7fV{-Y}PgqP99#zX|5GLf5)ss?9Py6H2fA`0 z|09>TAuYU^Nfii@w8zhc)Ge<0`G+X(e60w6LQw!^p9E-bMBhnX4;uLkjaKunG+0m! zgvgxs<~R68QWu(i80rbCYT&Nki<+aV-qUJImaE@kiRa}jO*c$Q4(Z<@Xfdg=54~KL zh$Z5rCG?B4!f}*b_j|Nrfmf#JemE}kTiA>~|NdqLm`X6-YDL4`Z`NNbUJLA?n{~B9 zQ^U0BPm?O2O&7b2;gUFyJn|d&NEuM(FS`k?zYC@!XuUqpW=%8@p;%b>tjgnw@i+~_ zZupp=^e(Y{VU=pH4)#4ov`_Z6$&kTO3+X%qbJeYY%)43N+KUrPnM)F73KI6+xXcaY z2QJH4l*Fp_A>VMX!&~wX7zc6NwD$xPt&}2tdD+{dFK5j9jAN?g>9#YLc%B+JQ^tcPVW_7u7$W(}=$ro|zRK|GiB zd5-`IK)=-`{RlLO9SnFn-=`F*77H%-Bs4zP=_Ftux-?dA9x9ci_2@L`BFx(3KBKgD z7Qn_m=ZMZwu-yY_wtlmm>;OX|j_}YMc6I(v=nJ2JAkW zZ5niTfp{ZE{3Q(R#g*^F>2n;dM+F~AC^!dccY{p{Cmij-cucX*;@^FdKZ%TWL=9p^ zK}6Ofsh;8;6>~`)f|rz1)GD6eW=KJD>!+X~576NRTGv-N4a4}wz7cCbG&ot~NK1{S zXQZY}G(1=H@J2>SIqbZ|qWp^*3_1g{G&^DuyF=RY2=RGUcdcguDWXHN@hx3;=iN^? z%7vG90(6&~gT6r(FDF)*7N0q7KPQ{iCn31h%X|c!`NIAtRPQ?*x3#qRFuShNfQGl% zu7`;Ip2q0n_W5Y($Bx7tRm&Vzim0l%E@9W5D`)FbeIYkh+S}-3c73zR(U>;8nk#;E zk;;wdHJN!=zcffIL_SSJUiS*u@X>`?9E^a^x+F#S0GX}?=bws6b~IE4GZE6QsSTX4 zb>pWrPskvrbwNxO1(=dVmpmrKJH!}NVc!Y3g6Y#+cNccif#kecH*h0Cm zP2SWE{ND~|d){PmLwJd_6rYZ$5nt3~Qs&VFfykZ^I?FEL3x^~eq0V`4k?IhQ6lT@S zo+q~U1A!){>$~~`lF_11F3Jv+LY>`44bCV9>^lsf%4a! zc14=ae+Aj)wS=7W6fhQ4#SN%=UEyyiXIrCKu*$T>#-kSrQC(UX)%u{Y+=JcqZ2M~H zgp>m_f$9>tt!H*DaX$wu&B&dyp0>aqgFL< zwQahQH~kaz`zO~72QZUsa9OsaBK;)ER#+0GPQ$VIJ*z;OR(jj&9 ztaFRp2 zsmvy*S5uY-;iE!>wp;2k$eCtbg!v~N1#)8Cybc)0RAGwTor<~N9bCjEtzE$Ii)07X zrnTXOoN8Nz9gy8Iwgc8q!tsU8Ht;X`V7=1HY-#5iGF7U%trmF=c?l-{w%|^@^tM>y z=IsfIoERpek!52(9n>~fRF>`dc{&zZjcl z8<#DMfstjF!X5s!su`ZLJ8=`*oU~dF+79Vo0Jn6w>>7)`(FWh**Tf`$!)0SNQJ4C2 z>mTQ)>jTKew0%F07aPNopII5xBED(7nSA<^zklyf-Gc4LHh*Y?F_w1)EOTUf=(-}F zE{zXncSFUoMW0jtn*4{fXGkR%%JmG-VKp}+U->hj{pCH^@AnJ!dPPp(rhj1_lXq#F z=n|I5r-CJU&PhY_%C7BjE5{0iWVQ1U-lGCqnM|lVloL-!2X%b=Y>aQKG zkaJ$KH4AMLDOKNWMdv>3s*qc;RDVu7m9>o8N?ys;;1qxSY%SpLX3UnHj6oE+B?Hyy z$`Xp2b5ZE2pdSNaJv>8(=czR}bS$-qCwGN&&DK{W$gInq{#g1_4r3#n)n+B+K<9 zSAzRFds0!>tiE&6DR+(dTm8n{?)MQdHY=!~%PUYFM=psFqVAh^7WE=8N?TcXmZ|#z zt1jvEfH6jRZkzoQnq+V20K5E)e$GVvn6`l<0M%8~FFkWda_c?CE-)mQS zKGhWnUl>ekgi;GpJTuaQ_7wX+rEX_Y)3aOen|w9O(}qtnOfAuCV=6(m#Yd{Zh!# zH$uzqM|wxIeAaerAszu%1Mn$MGV;?4o2Q%a)K<_ZVTP{TXGHsA*MJ){4^+$cP)-}Y zxRck}o8IwDJn{y*@A90`b5O52=oY^6Gp6Mq+(9*6lJ-j@%wd2 zxD6k;1)_W@%!tFU6p@pCBeN!{wp)xg^r}y>PQ-fqdX4Bq5Co7_w|V^cB8z`<=fpE^ zD1bJINu~YrLJEpE&CKhWEM+YZZoF2t>I*pw8j)KHj26Yr_ChA&4fbxpiPf>6&RiLS zkcE^lD?hoT7Fa3A`?3)WeTEKies)r=8r;)yVE1XTqv?`2WoX9M)iGH%>G=>`!^ig!yUnN8iqOU&Yr`-QY_=Dgf zze1Bfw7u8to~7yaMUFgEvS**b6f1fA_MRl`4qSO*^bUP?*jY4L^TU40O2?M`tW#`( zQ8|SHIe%GoqW+b*={jW)FGKAxJNQzTGkrxWS`tSenbeyD`3qC|Gx&KljGIFt_0ov4 z{v9gQ+I57lT3{Bg9Uo(Z4n-Dh^O~j15A+=>TxI7Eev{LomDzN+96(m9JK9rHOd0+R zc^Q)-uwd3XiU~K>SPGZp7FJYv*2G?PY#!^5sC5qJLc_77GVAA{WEadeHr_EU!zF`# zsMUR35zE-D%GS!#dy@o*MEYWe%1DdE5nV9UTa_DsN8ATJm>3cAhq(+Lbu|1vjkq9K zZo4#mG(&O6r2NwBo{bZmjcnwFQnVPojXw6%#AgxJYr5#|u;0QnY`@Nxfzw-=?-}e& z7~wzK%YHQaQH%N-bxY!?k0{6FBDLuot$L7we5S+s3KU=c%^LZXrDe?OO)w})xjm84 z{)nonO{$s2S`}2j8S!Q}1~+PiUr(!SS@AWdIGKR1(<-y=0-4C~&XCojFU!tOM?kS< zWk5_n^ryS&2$iZwtl#u_VkNyqq!*-VEK`u`DT(2fws!z8c;-zs)r~DyU)uOV)2Mu% zW@OZS>#bf1%B6(BxAA!4zSNXP;tA!N)K@{6PuQ$WohPYlum!^zPp=_=o3_qfy z&}*LL@jV~RbJGd?FH#L_0zT}x+`>Gx;sQ%$4VRD~(gKM$%)K!Z!Tn>cLb(wvoiwzW zOXet2NyT!>T9DOJx!RoGXwpF^#RCG@H_oA^% zTf*VYI%p9&y1Y{pKa7<5)aMuddp(Ng0w zUAsA&G#DY21|bg+-93+$x+xdA2{h#?2v|RK1S7JPQpPTTDOx$#7bOPS_0GKflFC47 zZjB53o(~v$m1sN_#>%c=QG%R!t?3=X7}7ncJX}bsM@)#mCXSef*s~`j&2Nv+?8s7X z_DhTko5#s;N2Pq0VaC~3y0P8r1??S{4WwXuZ_+}5D0h%dQd$;?Fys0O^&BBJk^KV& zeIluHwY&%=X~;?z{u;Ha{L4x#^_k?@iq*Hk)j_W0A+;Q5DtTkVo9BbiCR$vVlxx^U zlRc3isKyW5a}XoEIUfz=#wkK(8>6GN6Ms?{uH1W9vz@0EPo{NJv(kdiw!b4gTVYeW z6z9QI7C1+8Y*$s6W_)o3Les)8IAbs+KW zTMA#0O!G%TKCB6TJ-OT7%7goerUxqC{~f2P4lOs7$kxii5J_p03;n>u*J~^(KXLO#b1maaLKS zAS|7pk-`4$WzB_@(Ce4jEZ0lZ^rZbr2~?Znz14>5g^T6XvleNxdvCUmbMN=BCMA-r zc82{SKvaCze_hZW`7O=udVGqltFa?hXzJEJ{(N^8|7Y~sud1UlW zeo9y{KY%$YD@0I+YKdEwyx@yz>=D_|JFKc0D&jV>{r`jvvN$P5z;SQ{MYc7*@s zmKO%_reS_{-cuIu`-$|=7v?KL)m^Xjp{t9?pFglidujijEp#R5v+H^PpJn^nyoejZ z)_lAD&!BYw9}53RQ_=tG!T(EB{{j79>ezo9diTHn(f@hfyLs5dA87y2Kd0^gj%WHS z!T%Bl|BE<*et-CE2@y=F80G!)zd^Uy=+{NRTL4}g>Cj)mw>(v*n&&0wd)cV8axZT! zd!&qC10MqFUJ+k$DNDUJzxH{H{R1UOKIZYWByuK{D9CBAfh zb3v~Y%y(R3G!cmr*LvIm7`XmIo+tbZzhE$IL= zts`_}_3;%{rE-xzY(^yGQ~9Icr#s8+rx~_U{qft&g#sH{a}k!jLDow@F)0Fn&jvRG zVAKrDJ#JU2v~3e+$6=l3Q}vnK(BA(^ff6u`@yq99PQrL$uFP5~qA*)!MNSnDq4KSf zm;U15+HfT!1~Rp>>jb5Go-tKnxwAs%;zK60jg#@`e1;zsXw|-VSDwX)Tv9X7*=$>R z-UjTb@LS}rFG}0fT6Q_s;~UIZ+YFyAHt!gu1APT2R2WgYtmlsYCuRz~%>i<>07O4R z5{F8T$O03$;>L%GT?V^XBg0Smw<>0JMuymMRq}q{whrAZI**n1#i&YdO%Oj^G6W2A z^lMo4TT_9yOPBE;n0trCKZqV}i|Abr$1!C8?$)WyZe~55-hlh~c!(t-qiH>V*7!@` z1GXQ{yqqbXjzaQ;iTekwx|$nu9VR7ugS^nB)omal4o+@XnU0Y9$IA*5j+wI)zF1~% zd>(VuO#&Io3Ov7#qYcv_R`%A?tl@f7u$nZO*V=7^g&Ac)=*Faq5=nVWm4o1y@2HD@sIBy-7m7#eHj=SRPL9XzSfj zs=R;NfCsgvX2v$@(1!w6TOKr>(LyEtwIZ`B+^#{`wjYp)uT_5mpu`2i^R4EX(5mZV z0({SKW^(b#>?h&-47Yx!s8;>!N7979fZvBpun7u9hcdRr@NJe5AsHhBg%y&o%WP1k zm<**B2PdQG>dytS#>{O~8*+A&KjvH3^$SA1sB!hgJG+;)|D?VNvFn~0q~w2h`A2`1 z&_B!*n}7G}`x@tv`C9Vz8ROrt0s?O$Hq-wbDI5u)gp>T=DDdB@{QqyT;pG^jYf|o? z|Cgj=HqlgGEA`_|$A+*o8UwFr!N}+*j=tY)UTWSR^#iiM=;ws=|IcoO$kZDlg6Qq4 z0lV`Y2!y|6Tjo2aU09FQ@T}GCxnharEGzjAWb7p{uAXj}kM5Z70=*&2Emg>07KBQD zHaJCQ`m6nt&^z=lBO zb>W6N&p)Ym1bvgy&JDH@^V)IDY}%ChjOmDyef9IN7PtyBfbQzoC=32nia{)%gWb2%e#3 zG(gU(&|DpuGyCi4nDtMVMARI$sr3S@I`0rWg%Nh~3X}8j3f}rEu6l!X`TAXmC`ZVR zlH((`DXEWpHp=C+(zJq_yaAtG*E+-6^f0@d$zh<9P$A24;)6_3m@_J{z+C8Ex1K~% z#;DV^5==UZ5E9HT;#u1@e&~Dh@s{bDNi@qrP2b6lolGwmq2;I8<&*nkgRA=pq3~x+ zE#_;QL*KYACp#uYY^&OK{~w}mM@P#?Zge;RWK|?@9$c(Xtk4yh>IK}ugD0a@gxhEI zFVAwjy+Of0Kv`KAAF_*TH*ZS=xuMNVn_MK`ts2~Dyv@xum6iH8>SN9scb;k#54w;b%Z&!%pdGi;2&r1~NmWt}!wt zE}zS2=g-k^-go|EJ63NCf83I`tuf-_fK^YXvC5!7qqn~-DKcy||1L0)Uf+d5-yX{N zdwrUiY7cEK(BpTl#7Q6ow9-NLn}Fbk*Cf1_#)dYELOn=Ku4UloV-gh~q?OcE_GReT z&C`uFHC2cAa@LAXK-)`FKVI_ty;K?)Bx>hchz?ibpg<5S2c#_$y@=$Zbw?H{ztE_) zA0or@X(qLw>5p@LO1B06^y>GQzksJ)Z+@;vcJ1013V02xv};Hoh>Ta~out-fAk8uM zMwIdz1Bx0f>=M$SLmQi(vO6g+xqjq0b&~9^k!M(+bN0y7Enoq}rmN)cYVHD{p<$5F zkT+DE09GiBaxm;PgWrI;flMJBl9{p@@1Bq&lkF>Rm=4AWj?8qSeOEArt3i@1ao?@w zD@-qrJH=;ME_MI;0~O58iB9@yC?7}6$H*Xc-VMb7CeF&J2;o+``P)V}F_hWDsfJ2= z(#x_ZnwUl*W-^T`O9-N)-nwDJW``?z(t2OVJfhd!Bx3iJeTL*t@1*`MGUN6y!1R6b z+45>Ltq!BpXxa$Z^z8RvklAoUfE=El7ADR0y@=uN8K!}1$tUg z{snX_7ZrUjjXDFehOQv_#QyMde2dGWX_np1dVFj1o;H2;bk($5-i+@C{|QkHwJh9e zUPBrvP3{WcceR6suXkwkA+1L)L1SSe4yAV%K23m9h8M8TC$*R^tt3Hf7}W)@4vRFq z15c=qPI^`G<1+1w1vRK;nyK3m0E;oDZQi^JEuvOa1}KmSSBf%3vl5iId^TIN{4QV( zNHJeav#xBmzbZ#+e++6fuVDoZ-7QInm*mV$nfhb>y7vRx(wGvb9AK$@|I%1K}#wk*s*!kwpYGIw~(75!{>x z;#m7W)dN5PMseLeIwS|fXX-7SEU0}DW+liHO&0QQ;gH{^wJ=xx_16%Rx6$LYunWgiW$Tu55>k4-{yYuoP|DkDtb$@U{|nAfhn z+p{AvjUYoOdFzb&GnO=ZDXv^Y%pg!;AF=!0%|?YvEwYr%TM|{C2h8GOdIs|HPqRNH`gtqB-OI>7G-h)&(?de|B9IcA;$L{!P6_ip}wZtDMc7t5s!9-I>E-pjZ6LYJy_pY6+T zKTG9uVEkbyGw9v?bkZBoAD|M-Oq`%c5;HlwI+UfXDa^bb;7iT>TsP5Tu^QoVzG|)@s`G zi)#ymo}PPPyv2-H6Ng)lJ1)L&MOQ?)Ec`R~G>`rMPafWldUHIVT`Lb(9&XMdRo_8d zJ3=$H-=pq;y8#xvWJ5V?nS3c{wBK02SaEd@aLhTYr?A}9?o8;jx)%xgC#S3+(d1OF zp_pL=8g1ZqJ#%KQc!c(@*^2)!6u#DIwVTXUg3H%wB)Wi zJfto}M9{i%Bz-MSVdl)X7yptY^8q?&tdvUVO)#tUlQ%e3{-mX1=4YJoGRH-RKo?)k z^*_)WtOyN%0X@1W2I008Q0QVup536W+gH)k-b726c9R}o9_J{eiMNRB0}@#P71(qc z*WUB(gIv!RT-nQ2jj{7tZpz?5vwZHPn`%bQ-YbS9k(vE_==Vb=#|}L?>P53Q0Tc}c z#i&E*_Ix+w!#0Lzy1O2c%}wX+-ARD@jn~3sisyL@h59JLifjdn@GK}btsRM;MYX9Z z?rcs0xfxC>rCcEjCdg2whUIym-k8Nb^b`#gl$(e>Hb#yh@Z<|4X2x8}5us(>A~w>m z0`I8KQc();3Wq|Pn^%mJj*zG8XEOTQnQ?42_M7lw4vNFhNusGaiV%*HRD@>`7>D@T4>@x3^H^frt^I9>4zm!6}6Qs1(A&_j4&HTgY|{R<6_Co)`>@EWWe$grwn*~Dq4Oq^90ig z;rJZ+I%_x!a0m=2Oia`vuq(}=KCd45l)}4eY+uolYOAzu0qI4^{2GoDFx12fr*Bz+ zW7q=ju~`V2USK#K%~T9ockvu+u}YIgv@-#(qU&4&5nUIS3Pd3~S$xj$O0MJnB$?3} zOiG{XHI{ELiAaexJs1p-j2<9n*5cFH(?At%(u__^?t8&jhESB!8^E$C);5&(z`ZsdoY$iN%Mi6*KPYQqu;r@zh`(|CxzoVY9DWCoqrkPS~H z5XsBoj$9NgEA4dI>;_%Y_A5E&nRO<6sYi}e#*Ksu*1}MzyWkQEP5F}a<(*h@PzF)j zx}$Ty!=tc=i*&_94Pwi~bTTHRv^l<8k4;SAs3C=c&dK*+yz4hIwOA?6IkD;z~I4b7H}((rgGwjpU9YOH%fZTU;hXUgy(gb|a2 z>%hf3;fyFY^{bmY=JLkSX-auoV&;1Me)3fFjmTQZ1}VY(*a&e5aqZFCVzdUmCJ|5{ z1q9h_EsZ?4*IuDQl)zcwB;6j_cP$P?P(O`jSm8`uZuKzcB_ttgCTQJH;e>6W=Nj^l z&||E|=VLl_-e|@29t`diMk>NG3*yU=#I>!+sWT;(GU^Wd!B-Jsq-QNC}0AFr~+akr`pSD%doGYgkV*MAS&A!0eJhe(O13V)FWg>A}+> zSaLF90C6?0#6BU}a88vDN~|{gxurT1#V@W*mCN7nHYLQ;;tVzYjw_#bG%z|R(GFsc z7>BTsxDv&OYv#O~57hZkuWfmgoC@`oMyK>P^JfRHys)CwxVi9cn9|gc05#n~O^vm~ z4L(aS%|J)3mP+xN-_)n-%6oVdQtu%AcOqt4TpsqwVU*V0#zUP-cyKIeHRz7J6AP54 z(F)$iNn`|c{<97pV*5*RtQy;b^IbZiAdvV^CDs^8L&XG3e3tqBz<0u)oz4bweC?#p zjc^m(qWyBP3CWxh(F}W7ZY8^~P4ignr6sN`lXxG=WQ?zItrRVzRI=%Zj#F)bFjI-_;M8E80qMXuRIc#psNxdZGO@`){)Ml=8{A#g9B^Nu@%N+d zH5Z1Qa4&9R8QwYO2Mbpg`-C@qxk$+~{32r|1}&L4PJ0!7Q5R2#9}7%EZWKmeb%e6^D&9K^W>A0_GlsJ;Pe z4Ars7_`HGMkVL9b%H>>GriRcL18I>xQS6(l7b8_+3FHaK1!xYRjH?Ud;(}VW-U1Nf zv-&ZuKhNfw`X2xOoF~cF?<`Cqni@WbO6nHlw+Vgn z?Nz~MMg?gT%4(omq#NZ#J@wDRN19Wg1IKnmcR3NPj|#FC*bz}UnR2RSLm%^5rL~Pf zhfoCf@84t5lV%{g!l!`9LNq0f%7^HoUr2QAAgyM7RL=}qGgDv)tGfg~dxnIw87H%K zV|3$el1;nLq?rgFyuS(+k0Z%Eb+nEeKr*sL)$^Bj%tCvjlO!mrs!AcS(C?S0G*Qhu z9C4{284%R@x^4811&z%+TO?mSLCnm@MZKdl0)tqxfl4woD6;z^b@;~|e2QvO%u<3b1d;?~y0-4lUNy14+N^$=?2?hzZ99|wGpzBq+ z+KM>CZvoK&Sras^5*-prkTE{O*c~omL2A9pQbj*~W7jEsiH#K5t42#&RVck^ z8@bcLQVcDyGYf)%kXqu0R-a%9K-Zk_`8Use!R}&r1*&_?>Fh$CtZ9ASPe8MVwd!~} zD$tz%uZtCqsg1RqgVA1{2fLAx6E$QxQ0Shx+`CKuD7U^Weo-XRm@3_nvQLYr{wy2? z)@);Gsy6aT3G^^rfn#PS^5yD_o;)7&L@(%hiv^a!YU^~H@Gv1*lLRbUv?gTURJ=E= zSi(R6Z^m9MW$Y9bunA;Ts?9J>?zsjsQ4aMh*g3YOSQRyPsP*{F*e}ZLusB&`5_an zz(ZD>Eu(H@Wt|KzK&%NiUWLdi8)7l66D)2{1J@bcQ;Imp7FPzS4-35?Dv%Ckk4pw* z6h*4nQu5f=j(A}1k-eJ|Z2;An<9de&X;sUTzFx-+F)Fhl9`pZeq5q4Q5;OG>msej? zS>^e%FzSqGc!zwC}J4y`Dyha8U(8*0JnagJ~=ugIW-iYQQ&YngE$EMhq->UTM z0A?wjJ6)-Y6vUrqf5#7upVAdcN6Far-(g~6i=d*w#j#*Q3k<^oIoh9)QFY{K`mu!V z5sacjt5m*oBe<$L%k+5f7fVPsvXpFPF0iA(t{{-G5IH#nqBAH|3{{x5c7*TRp$v2P zG#-nqaITNA((6z&2TA@4Ylf||i>+Y(V^z;TqEe++$o0vG5s1@LX(jDOkTk`FBuj*} zGWGj0Qd3I%6KAT~sSJW9(3pEk=2VB;t=N*WKzhDsAoL9Ot614Bo!TG6u7B1zJQa8b&r=Wm|mouOAl&wi4)7J=txU8ZBb^9U<|(6a^k4ExTIuhm@Ih3=V=~ z2wnHl5SEURucQHc60)nKFa4T+1KflI0}srHyiwOto8LS->yNntQ!OP5+^jO}TL#HW zrk09}cnu3%mpwJ6W7sr^tgH+}drRLurWl`P)=9HC91I^2)pz+}`uWzL&mfhk6UZ;6 z9K7zSP?zDoX({{c>L=K^(a)ao;u#pmq`@d}j^S!yu!AF4=Y&@5n_ zj})&kNPVGpbcS0(TQ7GV<5P` ze*{sQh@=M!zZyoFp8|9Q!NO`QCq{QIFnhu{8No_TZCQjNjf%1^@jKqtN*gP+YI`;E zg&Nxc)LNR}2xyFYScRIgh>dt&VU4jiha${O;zZJ&0g8$x#&U2a_J_Z3wnU{WvD-Ab z!48HqQ`dbh^o#0&brF|+Fb_5<&Muh>j4r#mIL$d^7OJ}hOJz)u1*m{EELg+WHV@`5 zP!?1K(mxR640mZM4bP_0c{sYjxS0V!{R};Nnq(d_C)L&W5@b0hNZLdv>0y*LPO{)U0DocD0NYe2Be#e%8DIN+<-+t=TEHcngR_?+O`MF4KhTvpOls7^M?)oE9qW z*JO-*3j||87iYnU&qxQgo3dlfdFXBAD<*F;_qh)PQ9g)r`Chf zWH^;2S4o+rq;zkXfd*CysS9&zov3XERci339jy@P_Qr@`R)sd>$<{4i$yLE;8f1vV zE8$mi|M8&I9C2G)rt?bqE?y6lk5C{9y&kiHw6?1BAxm!c5u@|$8gYjWcki-@@`Fdo z&dI_RJP$g_wlXa~wW22|AxwIonZK`(fgK3W6mf-sWTV0`Ap$1hLw}aCZXW~t-+R4& zwE8!PePrMlMg!*}D<(xCO1G?7IORecwZt9cr5&TP(_O(Y`~2XLNGTb`(1L#YH`$`> zKT^d7^$M|I<4Oj=c8Y&7HeX6*p-NJek1!hUqyEPV(b)ZJVVIWVDZ`atG%ZJJ>(FA6 zpOxrx3}lFsDo@?Ud(M;sk`*>FmI*Mz67Aty5mE5#=(iE!hP~^^PZ{;cdcrw~XWLB} zhJ>O665j$Um8-~r!rUvnEkPM0Ds9}~3Qm}`aSKsdI z^>rRd?@S7H*j4V(?ATet>*C|OWet`4u$>{(OaIg?FR65g1!21wHw$wX?!&|4;LG_A z$=@UgrplsUR{jI$K0=mo^`B7*-0WEQ> zCIzV0M@IQaYyg0ZCAYd$KVUno{K7WGC|F>Vx;2+`)HzX-nXws^c8BSFihYTUD>7?L zKorG)ngr;CVJpFw*sGLj26UmIZD^x2lB8O;eL;p+pi)Cik4PhNp8S+qaP&sP0nJ^| zajo|-ZCU_RHQX#WG+J6@QR>9LFpj{6mMTrgfactPZBriw-#7~V%P{q?fFfC-5*Ut7VDV&=U*hNEFBv*)X*h3&+KRX&9`z z#+i;mZycV`7`Hqkm^>Ov*TO*FYphlgMW1m&*FHyw1;4}|y?jRdA7W;msE-Q%mA7?E zZ*1S@cCk+9rtVVnOzJ=0Z?~ZL_;uzj`A04ueE5CA@1Bx$;w=CDr(^eFhJI7t@6L#l zbE`*^j};=E)JcH{aOlTzZT1O?dXxJRp?qvd3RO(j=drkI=CJyz1H&TUS|+eBZG^WM zM9L}{7wZha>uZ~(q!cRhaGvk)QWl}ZwCH1dSo!jYIR~G_HtT|Pw(28aDlZw(zzfo` z6cW1P4D;OEIO#u9nE^qW!H`LH?`(HmS$*%fvqQG49cKy(*Llcj?Bg$iV`JRaj`z{n_~HtI_1wtZVL2{Q_gOtllM==Z%A7P&&_eH8kq-bg2qw1Rcw8Hm-i^zfZs5 zKzkusu4_|$tkeE};`}JRzaR8vt=b;NDJxYC7L90;CEMwF;zlHiVYjl;8IP?TF6&l= zP3;$cB_qE8J>n zBbGnsJnuWl=Xu|M=AZBTpPBEQd1q&`H!Im;@4eQ#*L7d(y6<&xnSa3jYf8GgRqNAk zo?Q5)M8Z_+efL8L?>{Q**v@xhCx`c?%b*Oe$UgzE1wR(ve7v!*@#8082pyhv z9S%-S1r?I*!X9NaMxjjQ-U$G6A1Tu71r(oBw7`&NKmR`)rC#IOX62Fp;n+IOlQx);R0QDOx0ph(IP{<3UA|-Z>2wK?PRg{00p5i8MTJEq@YHpf*i>>nI)y+nX;ET@9~1;y<7vsP+zWPX`^g~sPZk~WwksTRJwGU zi{cpwpbYBgdoO&5P?$_uA~58w#jJVKlixI6Pv&or9S<+qM~Zonv$y3Xu_DQ7Qjl1u z1+c=M5U3Jtp2eBVF^-a$Y4Vbn9>CTXrF#NTYGK#-%BpO=Cui8r1+}#mDp8)q2t;=* zL%GQCj)KMhSRJnYfN>wL3&a4nvDyTwHCl3=bWSrSSkT7}dLSE>4v#u7F=wK>`QA_D zRNlzn49A>`t4myklzdt4>|=?)GBvg+W!Bf0yD>cOVg!>`R;UyVYyB_(Ev%>03eOJ;X6 zDK*la6ZF~4As%MDtS34sy#*`E0sn{AE>}arDTP8 z%@}(o0)33FRC8c{J&Gw3{DR7z^l!hqSLhjA!J`=I{agRg!}oarP-92~?7(D+F&em9l z)-#qr7L>gN!po?|Bq^Af*(pj|C8*{->kHxq+v}0!w^Iz+Y0b}chu=r|fB^{rg|g6u zP#)IT47{}F?{kbZLM^oP_K`8$!GGOm7+640wSO_n{>(ko!R46 zEao<>6{cs(tdnYS*QEt9$|2spl|m30sE0MXivbK;kZ6!CPhl5=T9Y)us2tipc)B+q zp&0z=rBdIdb9}w#C>s})LGtq6X)n1I_7d~kfwRzrf*Q0!qgcI7F6je2s-qP1)}{q; ztltnV3nPhoHfqn5yyfJ251Ip8AxV>bL9M6~Aqs3(abi}aC zV_Ueqi|5^AG&VmMCO|8rkeULx?&8Mp@ES>q>E*TzJpbG%k#oQT90&$u#%$SUY4g>n zh6!5vmA6F-{{C}9`c1|ttTCKF&7UP61`Af@E^FmN>)sItG$W297B2opI@_8px@rQf z_bLk<^TSfzv22{1E&XU$y#WX}fc5NY1AFaPkzLkqXX}2P7oy-r_)sAe%oJ}fOLsrS zT6OMplJLU!rYtaQ^f^wg!u5*c3`N~iw*j{?%N!+EYMw26i7zfdAJU&BO(%X+@WZ7R zxTItAZ&q}-ipTwAJQA6mmzPnHDh!j2{&8a&Gq4vi9ZbLLu1&Ia1X;J`aG*yI&7z{& z{K!HF7A#u#Z%L6YLN6+uy~PNOtMPlAb;rEibr{?hz;O zGSU&5!K$EDl~Kaa**{q#L=b1~mCnkcIscYdc>o~9Wy1b2Vpk)^Vrmz@M3t+WasgD* zqEb5D{3Nl_+9!%C_rd35uhuMwp8!lt+&In+=xl-zXc?@Xt=SY`p*T(a3tlEBkpgRJ z=8Np{+aqh){RK@&Cu3@x!b}eW!*NN>C3~x_srG;3G)&)xW zLwgKC?;jMq&ZjY)&U&^nG(zKPJZ)q=cdes1&`q+>${k;0S+J7AY;{XR0~VZdwd1MX_B{^ADRG>u_6qr7TJR|byR!o%?c%kd?cbgb7fKL4Al zJ7zhG4pi&l&SU9qOk;MNUp31W=UgNkxoLXO>SmQ7AzM?}e45rx)I)^RC{MOBu?^Hz zQcIF(rp~mKCvL&$xpCQnECbh;`6EENM&T0_agk^)c5~W^!yE3$0Pazrn#DMR#&Hc{hUffL$JUr^;0&PBkfTD;=h`uCP-O=XNl#dE7d{#nK)Df=09Vs0 zQY|>@=7*)3BfA1=NDMiVju0NYKd6~jGD(bS^wOM&q_0eiQE!}lW3%mq%~pn{%J+s9 zAm8Pp_FY7aAu@?i>xUh4;->5kZo@LTXr2;V*is+CmA_pQ1M3tZQ8s!SZDxhcP~^t% z?3uw9=JY9W$>2y1I!@H;loMBqKB;+k@uoEa$lTPxK~#LCV!ia@hD0>E2FO?F=%<<- zwRH8Z3XwQ5PTS_BarQ{tT^>?RYka=aynIWVn8Ib6d>{peEvtyconKb^Zqv3FUl?ph z!yC3aY0Fcv*2Lz+lLaj3i3Qm`ot^#*6-TVd{RDtbTa_4A`cFqPlW8vas zim7mt0`Zj7tsjsRBy_W%$s4C^(gX?wnYu)YR2JmGN_nSY&_4I5N{`dB!1ypwQ~PI5aX^_ zT@=keYe;*}__xBwL)dzqifnQ<+08#_UHo?GO{dXACwjKhALrdbO`sR=)lYy!9dv`E ziHRc0!T{!AL7?6G>S`h;1FQsxS_0>oei;F-~MFOQ`UtVxLlIn=cp?E zt&80VUA9fLnWWpOCiw&fu8(ndgd-FtW2?bLM(`6cAP&PVk3*awd0@MDEYfy`5N_#jr*iPfm%@N4I zgK>2U`G$vxvz79?Jmu76#@yWZdF;MCGc9fof|0{HP4&yktdJ{e4C@ydV6;MD^{WZFyR|$&-0?;{?q4G-?4e`rfY&_L;)HdbeW8!rLw8Q4KITL z1=JV>%O<@T3XTa_!Vt-99xTP?Uli17K+Lsc2JF)o_vl8ujf)ChipfA^HAe+f2^+lG z8G!~8mGP|&JiD@IdEY5<}5Db;)D>9GH z6}EG9*p1VEsgC*B^4TIl2%ciCB5mRnO;TBTC!kNa9*R2&$Owqeu?KAVYr%)I=>6la z<+HUNf{5`woM{WwJL(vnYhY;ox=eZ2N%~*L;A;A}z3GPXi+7lV9nX#Sews6{Rl}kv zR?qkjJ)$_znzR`AUIsP}>OTz;$i4kT-lsZh17}T#&_h4hn_IfJ&Fwl_$#&By2A1s29ik- zseLB4h>KeavQ%tvuQQhJw4TL9vy=uVoFQsKsCgJz2av6z5wm;p%19&daB^?)tMf9s zbK>ll`2Egj#3CNx)H9xhItev8H7-Ca?Tu^0vcXi?3af2)Ym2@pv{(nlOWi5M?|r7&!uGB%glNKio98abY>JR;Q)C-4 zSOI%fK^edr-W#&9;O_{g5u$O0l}T1z7S(a$K!<6FVv)9M$sRT3xt64u4_50DH*`V6 z&v*#rX+C-m&H%Z+A_zG7nRNq$UI`+QH?w$JtGAgCv8M9@X&Tw&=Kdu;D5EY1%bA?c zG~>?X9bB-({AHx1w2~bs713gLca}W^jf;~7Wztt9gZx%!(yyA z)&HQgU2undxHxgj#pa)~rk%a`z+v1pl^?0oJEBY#++KjM= zz7ZATCZ&h6uEw~ir3x;1=N5Q1LAV3PN8%pz5Y^DbEO^W)-aB8$9sQP1sX%%h=!G7% zGHHV6Cerm4l0$mo*)8G5qRiuJ;UQu*V{qvQ&eC%CG|TxZVl&cO${%6eAvWaUjzuH@ zap+pPp^{`xJZrX|1xe^*RkInC)TvO!BKk)@HCL7Oi2h~XF)q}A$Mn#m)s|2u&Jn{H z46gExrQ~ljP8^Koo*IsafSG#gioE9RZ;#y~dstCMi0a^XmY@257>EQT6xQJPZ;j~` z&Q+^5Ut;O8Gqq3uZLatsx3|cw@~HFEi);jahR&Dcqa8peCx<0@Oeu*>AdExboZ! zP?zCOnOem_hT`OW7-OZKtcvzUQHFN$Qe2aLmbI%$MS1pzf}|fBdctI}1e{82plH{Y zci%i{6S4j{&Fg9_p$6L2*kP_!zA`8yYeSyY+qlouGzFwNU%t$M$&btU7qE0Ku_pbFtBKf z<3@1s^$+L2C0!A@HhTYm?;xZ3=4vb&`#GZXE-F6EuHmF~KH$k6^#Y^0e@w;vscQY# z0nKuD``Rx0cWB$W_t5|7Dy5O>kerEJ8QYG4H~+7@_O_thy2sn=-rvibnjU$XO<&y^H9I1_>&zjaNThP#luUT!Kx`h z?NZSotdpm%0WV@@R^DJP1Xhkl`zV~wF3j0yKHd5JBw5qn#x(ldwaZ@~MjmONZiasz zJbst7{et87#}|IP{ckH4FN44CcVbET_T$ednbW$T_nHPkyKKbTct2?Iyll%BU-D~h zG#9)St#R=d#u4NIh+wHxvGp!vz_# z4Y|GV+FtlN+r*|>*a%h- zADX|Xp-c#0wQ2=*CCmEEt0K$Qjf1jXYmDv7)wSbjxAtybX!^h9C9C#NH)M2u zbuU}JXK*ia^~J)6`lL4w9OI8K9rK(wI%rYeAPF~~9bO@jknt!#lm z@MCf?vq@8tSluA6_#gRg?n$N61`e#6QJPK(-4$xN>z8CSohE(1(@A&E+K|`r746^W zd=j2ir0fxXZO3<_V=H4V3=A=cZcUT$j!>gutvQ<%7A#Gi(6J?fBAa_*YOi_ zIY&yyuI}y~*Lhw~b~YsQj|y^T$?!@Szbpu{%O|um$i8FInWm&JYh)jnP88yVo$=TDHGTjl1qkSITe!t>W!mX`lVHi$TwIZF-jIV z@-}VxMhoD-Ub8GtQcCfJ22GQMG6`JVDAo2Pm>FfH<} z)#@+paVJK^>g{HV+1^jU;{Vv3f49Mn%v=lkAx6*k7pPdc)ZBka2&!h|G`Sho`}i}9 z#n|q+_*H*Ob)W$B(g?$>p#FV1!=#5k*4)dvjQ0|d{YyEZ6{yU%8UK{URjab`6Kq|Z z6H0&>+xFh6<3q1su`8S;kiH?!(^Oe=H7!*{AT)}OGdHdAM1yo~s)i-9qzWP6K3F6; z6nOHwllEydqe|6=Vg+7AX0{3fRF9FGRA8Y0CSlJ&KoAq@M-nJSQ)Rh3+~y1C?8Z^e`L z1k=1+XRmi$an21ylh2t}mTX%Y*|iO${@3L5zTSupQZnc^84OYgVV};TE^BbmA+Ff- z%3nJmjaiJX=vwCCLhu2_xIX( zr6yCI7UpwxEtYgT?AN1F z$I&y7FEGSg*C`M`O~kS=Gp(s=RNci4J)!S?^D_GG{&|lQMQ_N1JPaS^+cSfUVY*M% zWTjp+RR!tMjiO9mUwc<(2j%0|*Tvo9XjsbZv*_6qn=$^hqI{bM3>|91^hD(Zt z8$*cs5`zq{=HRu{s;L$7wa@1 zh8*~oZQcrQ%19JrssEKeWDVECsNPPMh1VG8VgyBS1T=FzeQ_J@@gqTNZW?9bZ;tCpVRn(Q6WN7o zSbxofbg|Bs41371BG3+DdE95YC~Xjcj+ngkTOuon*yj|INcVXCuD&e8O%B)GZZv@X zV8rV=2b&qlPyAppNGQt_Y^Pl!Kq}=l>%xdZwv&4kkmH}Zsz$13XvSy^m>JL>GhUWe zSw8^?eB!cn7?|!FRMfaW{)eHB-CvVi`KIF0}*OGvt z4nro?IfP6FMDt3h6)ZvlrA(trSP-?G)`r@!hE-EsX3H9`8O3=o1oX;G?5& zq%N4;?aLeBzQ>L4Bhc!#=CR1;4cPEEa47%VHa|(AEsc!{(4yErJXI8Df7Cx7VDUh^+%X4r5)kFvS*KFE$i#JE^YFg8yhyxs z`i?G=#>BSt&9o^VuoYwGvezfczx=DpTU46p3@XPD2?k=wCbNDbQD;0& z35VQc3O|)D5~&iJ9nP^Xh#6dkGxpt!XZXo0#*^1Ndm@TWlQ1 zS;TD54N|>P>VKe)!V6T@-OQg(EUP5R!6Shh#ap2*ye!{*%K5jcOqh%EfDBSE=oI%$ z;eU{#duN}$3>o+V{AFlUEVyg{0lj<}`$<9Nd-ZsyN^n7QlJj^2)P||8D58btt&)~k zG{HPQQSgG#U0EZE5eo8RM>W)%j<;XVG3Y_-w~<>ZX^jtw0cNw(utKq+fV$|Okmyb) zkYu@#DXnDhMGoaw0-mKr1uCSaY6b49+!o*Lym7Ak7wmvqnMfkkiacc?y~&astHJiJ z4K;Oql)#sPCOkRq8pKG>I$D`d6i^kPht%i=f0CHpYoYKjUlJ9qd@7khBPJrrv5(5* zK=QpIFOT;o`KCSQ+b{N>7g~;^Otc4s~z&QCSD7mp9 zL^%6wAxOEVi~rL$K{rJ#GmusiR6c}&cu^;aKJ^R1rmq>z18W6}U> z=En(Uqs6t)2w*GLQtec&Q@sCC5}bAeG?XIx;Q;$g+?M1yRrv*>UxBIz1T+mkuFXgm zi2?Wp7W!oFq$87QK`F67KUWyjGV)<8ts)jlk_0m);Rpj=kHsTzj%jmN@s|76S?~Er z`S(JF4{{kcfSlH1m|972r%>zit=7-k$oh4bUy!DGUII1X8%P=!W2`~(0P%MDvA0d< zAHKiv#41i@vMW)pe%lPgu7p+LvVmaaQvM7OC~o7N|vsq4{5Sv5KjrEvYd^MuTC z{~>e_OO`30E?0W``Qp8Qb{ry7DTUjXUoWkw`Bug`dyec;9Gn5$h78e9-UPaMF93jD zR2kf0dGifMt5@@fktD%QD-3X(`POf>5MeyXVaqpp+J2_@6{krs%Y#=6_D%?)NyIc> zE@m^eBvV3?t*hTzp2Nv zKHwgN+(oF&pF8Fp&KoGhJvhP0Kg-VINg=-3sH95)spc^?>=-8Z_Oi6giGbIEphM6Zi4i|QqN#9L5QqS|~nvJZWIidZKs28)Rwh_Pe)qS0I~geuGeHS*Vhw# z3H~(43QIo$-eHd`|Jje^u}JgYle#JLaY_73u2Hiycjzqo*x5t7dkT5wybOhBJf=*|-|LVaKQeUt1W^ds`3x}iHcj#q=GByrZR`#}a;B%z!}ixNXSR3+ zJf^r7NhchFg-jAeQ{r;aj>?p7RF&CwM9#Su(_bqu4L_u4Dg z9dmEhHx1bTcqkVys-I}y_O^jmVCeeH0xdweR2Q>;tLt^tiE7;-#zIxTE>sFKNsYp# zT9IA)GZ#@z6A!ka_7Ro9lYzAE_srp8Jw?dLDh*+uy<*B!GU}v~P{x7n{dxdnCp%Cl z^5DCt4nrTcf8_&81u@cli|^iM-|l7Rq^>sxW`7dYK!3p2iu&VMCw?cRzEQ?fYdiG& zr(e=P{;yh%|BvUz1Q4n(U2((J|JumrS#>2Iv-q=KI@W9K+`v8L(Ynp(6&*V$WnIPg zS~oBFw2w3QYd*TEOHTjow-1}iFKo5u4SbF+#vDVBt&P_vB;Y3NUscnL-GV{pib3z# zxWm+T1-yj3a=pMCk7ejI7wff~+F46+xdWGvfY07Z9=!WFd1Ah}C=syeIsNX;k-6_5 z3tqn~4pz6>j880COFt?yo_aKRO%A(Wzk-Xst=E20=>gUuvz-9V z)9k%>4#RK6kLS|GE!MHw#i166V?ZMvo5*@)+;g;shri!`bU87qz;-)P!|m+dED=%u{qzVtP;)^nigVavih8EA0?$|w~-s` zEb+1uioBpfXHg&4iR%A|)EY`F>qwDb%W5~PRS@8^osW(u7FiLDx-jjyRrtNE+hBUTJz6w0KMtnn$WQmo=oeQI=;>% z1)A#GPJ2ca`y(WTTH~$H<_YOfh~MLK2?{1F4R@_T<1)PC{hzkjF%&?=*tky6aYVSl zjq?lA7#ytdK?=`8WaP|YQ?(Iu4X3qDL5xh~$2@Ktx`i{MP4an`mJ)Pe3)SR#uvem2 z`$-c|1tM@LaXrQcd9VFatw(ZD?; zpLTSBsbSmAoC-%go``O-ypn1raQRfMZd1(ivdVSY_j@)hGvvOZ1`l=e2}5 zoG8owfk0kBznGKRjz|Cy5Bb4qvBA?~WdzLylTKwbL+T`lZX&Um2+ub2LTuC6AQZE7{8#Zlcj!?G@?9Ml&T?Awro<|~K( z1VrhbJhY9(Y!qzXbqy+`b^Bz}WHJK;80*wL)sAkT+V*P-FGnQjaT4V}#?iAln$<8x zl^4i(LB`*7Yl!m5B|Y0oBe^Ab5gq{u0ET3MbE{yqc4H^PC?`B=robB2!o2W)Vu=S0 zp(Qbaom)W|l1B)3qPsE5)4Gv{t{IL$6X|Glt5FKoz_Kg-_+U7A@>VA>aEZnY*^oej z>PHDUlc&z8cX&WQ6Qu=?l&MQnS%4sa&={M`#raMR1A7ga+e2u0f`}i>%39|I7T??+ zw3WcX^167uT&=ot@!2I+Bo-^Nj%whNo~361VnV`1Om)v73*wE8gTN%l1;r@=dOEV2 zX{)wT?jjl0TG0rS<4mj5Rei$10+Fp4H%<2;ufy#a!b$GXuC28f@=D@xRudcV&yh!N zRZ;UM$}Ww)cu#o`Vxru4G%R@?nN^jLhDm0O@+xcIcy^;TP}PEO0ka-_`CGu@O^u?r zu`g*saR8gdJW)L`TGq zbddK3QCoL$sW-qf-oAmckxR)n4`yan;zcq8+sh2|t!if9EGM{`dF6f*{o6#H`7zj3 zl=Wn)Jt6iJ<(FcrFy+tLtiOn-|5TIwB4(h7SzSFgYTg@k zpL~r~S9({qb~nWValh=+k<@XXdV1#|R2eH}5h}OjX6dhyMsIm}nK4YVmU5!X9*9x8l3EJWXaY%R;D`CJb1|CDg2?fck{!Lo^$~qk}#no z%UE~`M5EkW=FLU_>VkxuHQeq2da0i+s0p;_5}l)5WlF*pNHVrGEok=H>hL(mAY(b| z>G*7=>6ZAwEdgavP;YcND5{;U`w0m76-Sh7eIk&6yg2{e=TSzwuk*=3i+CUDjD(yq zbGSm{OF9n=E+C#oSC$wfp~md-mRJykiV1-!d9g~fo)`J(^FUu8Z1Ry)5~v*ml>n*P zhcXe}(0(*to4JjZ&f`okeKxy#$L*^;(6UgvcZseo?rM!vqr|g`y=QyLMNzZ&eN^)w zG6?D2K+9YNH1WVsG*&FkMc#a0{!4E3j|QRuS7CLeq1D<1=5Q}57A9VL1L_61nFZPU zZGksrRDZ{1CW2p!=1e|tHz&snVO&1D{N3&tqmCs<8<%N(BKrj@Bg{Vi1iaX#(PiSi zYv>Uj>vnTdKoQ*sI`g(+w$y#9P}%!g^S@!&1afPHy20MSy~2}U{e5W+dwxDQ{tj@2PUdfp_?7%hs8$9D)M81B82w7PRxTW{wG97t9^qf`*qXR*u--2Im+ z4hNDODm#dZh$ZL9sPAhA_5X~|dGq~=5o>pgzkfa8)D6bO{t^FmUv%xU#D+P*&r(4t!+vxDks)?2otyL{+UO`JXylyQ9SYCOyI@tE8f3e zet8bghd*rk2+nc=M@UzRbsM%?<3W18~Ge(|cG~K>5?iP+uaXW-PQS&jCtkkc>q!$;~Zz(@QV(b`~b$@oHt4 z;(K`Nu4c?xlv)$(ljq3=@Ut(5SBL9_L9z z?iMM85w6v(D?p~CrJo$2P0(K}Za3ufp7I7JptZD{#Ico;PBnD8=e=%-MXi~umX2NZ z(^r{?q{I-|%zW!XF#Nf|nR--TadC4{e+_@b+0pY=TG(Z#sTHGrN|s@40LS?tauQTZ zg4Yl4E=320)00=CJSy+!#NUqwAX1E6V|mYhzD96NCLV(<1Ek;=6j`|y-JHw#K)i)$ zzZ|_9H`e=u%;Ml^9PXOWRS}C+dHcZt!s-}->uPdCV7Jy$WV2Wfgf4}$_v7g=)ERGR zcYtI_0>gUHOG7r)BRrC}2?%b#>iKMT^h@v1pkQw!MZL4cL}*0Oc4#c;>iw=&WriY) ztL8kydb-X$XKC$CqSovYmQ2QO=V+mIh?1n=1&xDQC1!QPE~p&-1niV5r1Tj?Nq}>g%Gd2E&He<4KXl#_i(nksSFdV#c%J~B@aezmL(NdDkIIl ze-%CCuu{yhO=_9vHkw(pp9*m8X>YBv;27?QU?m-G!c)&jV;G7JE3pf2BQcC@9Z4jba1cg^iN;4r2Py?cLQ} zeG|eBERv4eUy?FdD?fflVG7i>s`D?gf%Of&TxnV4|+PPwe#cevyollsBHb zQR;tfRP{GKErn|4cD3M~dZ=v8&=UXvu1ck=%`JrJlBw^PSdDWp&!v2E1^J&Lqm#l=TAPl*AyJ|;1_bDavXGjmyOE2tcDrQ8j_ z5!?q!V^T~?zklsl&?MAAX{u)44rauu_4T?UoK(mDbxPgpD>BN}KV1?)m)SNMe@Ax3m4TY* zE^g+9&$=)9QNUudbO1}y{+B1=&*mSN5^~%!y>@{vZcGzx$luVHM7-?mk^pMpcv>xf z<_5c5^D2^YGyrRpIqt5!L?_J~ZnCs9+xt|z-MSZ}c7}KPTYb%fAwpHV%jk-wgJ3r} zOyI}CFC7V-y7|hr;I+6KLYmn-mqrduO_$f}*o=B@!xb$EWasSg*rtOH(j%q1w=aIn zQZ~u@MEpRwx}|2N^jgMKhQi*_zy!n-R&x3mG&uWv0;08SB_b4vienA1f%1U_niSb% zaWoJ9olO@936zr$APTiuhEZxxTc{beL%OJ@Ma_|s@0FBf>f zjC6|=8uUKH#>YU|4TetwXC5~tuv5GtRB^%~@0R0>KT$ieR9h(zlq_iubZ;rCo&o0E zc|UR5_%}!=1oHy6QuLL70_wMzjuq`3B3`^}5;x2g(Y?xk-Y{QYcZ}_P*wL$zduKKO z9Xqsb+&o8-ORePHNr5N7ss;p7)l(-OGmy%rfYZUHuHG|#K~z-7_n+E$6}($t%hu_t z2qU6@x_+&9@yTZrcjYf=QvHOtcB%eupK6_$pVND?)LBD@N9KklBZ zIE}?hv*HT(NZ=rm>(^F86hN+GqGNMPzUDrkhU&xA)bHfNf%qe-GTopTZ*OuhGW`1U z-)SIU&a6mYz3A4xNPKW4Pp@^$=Wh8L1JZLvg5n%FR+CXBW=u}@SO(f~c|W;olieU; zk#Zn3wqw5pz{hhZSE2AH+qsu5t<0Ekp%8Tyli;)&W<%NNl?Y=S;5?#M^=Sn)CZK{_ znq_aaMm2H74SqJR&si3(z1M%m_|Wl*Gt2VKvX{eTZ*<<(u4Z&n9)mUl>$DqS2Znuy# za6KfLw?u5_P3nwmgGg;Hv2Z)fEk6+cT8lZ##b=JjU>Hw>_8WEDMiW2&{s+=3;B8IO zgC5%p;-6;g=I+DKpB4q&!PC?7Wh>hoY?taWY%tpWeobSZ7AEx|;kiFO&cey)Mnqgr zJy!-LWU`F5@oIe0Co6QU=T3!RU=802sv(JFMyU5-n2KtlZFBU-)-Q{s+8tc+6Y?sR z5^h-%p1()A|GAs%OwZ+q|1x>7%POvth_n23s%!fp%D~m`d&LGdEyEYWH;~y+fc70A z{3oCoPz_n)IHkGP-S&t4%e+U!7ijXlPs>XcpM9>S*+f&V_(_#L6{(&kSDR5~|NpE= z5-B^G?4P>+xlQP3SGP*HiQ;u|lvv~5d?h6+yh_f1YOSqWihg2uWAC!R60stUQ1M3<;J%m%@6-6(pyGP?}Tx zyYF;l7tSv>gw=4wEI*4(<11Y5JX$NI(1o@jUA_$9CpqRiQUIRZM29;s8BAaGW?vS; zd3ZsBnUC4MDj8SH8<1W8ReE8>$$J7Klwue8FD?zn1&`aWg~gZ_`<7Yrd%Lz<@ml)P z$ixd;=J|C*&}}kkGXoxZ|8Art7yt6Htx9abPeA&0q&6`dVE3ldFi3~TQgNiPyo9MN z)A698Y0dCM4~{h{tvc-~3+B<`A6B(h<;~OV-B+0jrES*s(7x)F*ITAZcIV6eR=Ikr zlc1Pgnc<4-m!1-jVfYk}kXGFrXN5oBDi)E`=D6E4o=m6Cx@@Gw_0*~wl7r&ANxW03 zDqUIXqiVi1=I?ru6=Rd3S<9um^f6pOA($<@Nzrydyd>IsCtfA*U8JH#*kMWA^YR^} zXdMWqIA3cwj?A}`U53Ed{NCV7jOtKU$>uD6L(J|9AImtH7jqYqKBhKR>ygsnKB0)o zv_^)!@yfM;ac8}Ky-}6)m`AtrrQsW*PKeUrf&hyCyK}7%{zgFtErDlEe1vtMb>qKp zQY2{SLQVVP6dP+kV!qZjn6oS!r}!~k^s2!7Bmyg!z-^Y5?2l;91f`5ESL2f7wDKG$ zgzOgWg;f#$Di%jCtCxgBNH0{S+mIE`IA&_N00qGZ4; zqoRXZ*vX%-)`rsK3@e4^Wkce)k<}?>ewhT<0YfXL#C|_!IqvH2&gwc>uIxEXa$;>F zy;QfZ5R;dd34@FQ2jfcWReq#KpSg#;gn3*%01R`ycQH+`m*h*xxNI&1X&tr5|bB7&?r^ zlHa?Zb=2Khx6`=i?$Z(RKupQ9-Fi}b>AX1+!Lur52(x>bf)L2ma}uoe5GxrG+v9rr zcKh#N<}iHOQpP~fXOc^sS*(}C*f+C;8JdoqGat1XD$4Q}mvyhUOp6QPUv{AZmG$04 z6)jolHRkdG07qzkxIzMtoly^_Tr*{L|Yev;3Ar@u~seXLG>#NGc zd<^l)tg-;UNr4*Huo>Yfigt~gO-SFT@2h`5_GufKCSqNA7U$}#^W5^Pb! zSt`GD#&I;mCj3kk++J^Vb-_Yb*|uCf@?jjfICGU)!64)_S0Cad!BrEJ=N*uJ30T%z z${e@JsN4}y%)tYA&0See_v67;NQ^794<}VOqx$0Q=f58_+gScpzDapU8M7nGrMk%ECUhN>u5xv#EbC=Z0|D@?yqQ^^g#;-5N{w7kj=lSHmv_#^Ab9 zisT68+mG+qayEk!gd;WP_!rMX@J@7r%(h0tyL05mfAME8MV@&9n#jHugqN&{|8;OL&d^%mhQ|Iub?$$h{@ZZ- ze}NlApw}`9M(vSHkG>5={K9mKKX@}sM$R}BIBRNoy6(BYhEL^!`MraTZV9)uO64mh zFsWm#B>0*a@pMjfu-W1~RrgyXAq=Qsm-B+MWBN*kNXHBw2npgcfAh__*nWtI4b+&l&6J z={hCVxws`}Ow2v|J;9XMxaIJr2kouHZlC2GNikUDo0oovzCrW3H61%M#6K0OG7ob( zxUDAzrM%v)vq~s>FMr^wXC2gtzD>e+uj!@SN5o0Z7*U|={bxC^x1cp^`WJ@Vg}caL zz5%t^jKlDOaf#|#w^fwkXi4n&9UBF7K$Lkj{!qkqI!o${L=2&X)=Rs`p!^~Oe*-bV zK+lkqt%XA4S?g;)^vKfoCxAcO@52(=B5ro!v#{5!BRJMn;D?*igKfbpdv0!RL5_(M zu54r1RQQ8>d^PD+2EdQs$-kK7)w>@e&H1oTzT~;e(=XWwb9HyH$bES`GMC-bo6n;V zu6s>lB36l+Dd*m?>E}Gz6Z!4V@o&ous9)+>q~y(Qmc5utc*CJtvtO?xwr*{)7U<(X z$GdR@=!hhT^9T#*+?1kA5rC-ZN?g3=tQv?B8|n|>1S9YwUe3j#)c~1YzdPIO_QH?R z3$WDUVnN$BZ~sd-72@h@gw2zaGLV!}4V|*H_^3usX{=4FX~Wiw%2YsqV`l9mq7D5w z7sBSJ--awIyRdjBLK;C!stnF&(^CPq&t}blV+74&qn#nP?c|Zn#9dPMtm5OYr7;Jh$sFaMS9s zH7-qkr~Pocx!WzY!Ac_3W#Rq#;wL~CButm~CYP7v{Ia*a3iP3CQjoBOy?#^wA0QFW z+29cFc+je+I26!;7-y0%Ofs|E=?pT>DrUf*YNhv+k-}+L*ge=Q3y?CPWG#GnBSA1j zpmnl>!e?$VLXXCL7`EbQ4iUI;GolZ@^V|caH6@^`_xNfTVIocNx#sW&Pm*^wd~I&XE@zQP-=ETfWEK*Wi}iMKbW+UpDb;vK`GoS>-55x-;$uqV(` zVuUxMARsb}5DP8iI%lQrFc)iOKAAXbqA)vUhYf=!7@2rbB+ua% z{IhPr1D~Y|(er(%C|B?Vvdx>}US)DaN#@t;n8272IT?N~Pm z5Di{ZKu=cdYvT{Cc*D3JYqUpYd%9NFHqIBsYN}S{++rV~@}egjx}9^jO_Aw2@YnQL zBOYfOx+#1f^pzQl+CELOY%A&WzFB6plJ?wRYg(6Y6EfNLCT%_aO(f5Q80SB@;^LOx zGVa?2j{FujpUX38@}#T^3Dzg6-cQVHm5&E|qc z>A1z`Q@olO6n&E~e5kH&tFERnSFg@HecO~~_Gp(M2SVJG(jT!TO(mvtb^0W85@VIk z`sj5T=JK_-rvIPz-aD$Pw%r>HfdB?V4IPwj=)DR`=+X>F{ z_aas40s_(nRHP#c7O;GI-ZN(&pZA=ZS+mxB-ybux7Hfst&d%P~ef`=2(bpeH zaPM|_Dwc?|2wL1Ua{Bedr+7I2ot62@TxqbFWgN*cel(5DvSPZ@h>A6#w(>L6TiQUm z9&L+oRv8zU$)x%Rb@`RnQZV+$%|#ytnwQu5Ifd02C}iWFq}}eBpJ@gsY@(A#sgbj@@uq_bLONxMAK3riQWVT-&)*4jK0<2`^y2RT<%KL>vB%nRVm zeat-LO4@{^!^<5j&1-yR{JVjBsaQfq)qE~chNT0{zaBs$bsOex2#a6xU6~1MLHSp< zdD1&tw(zzieZ?uJL4BsL?CBx#{B`NL3ilupOSJfdoJ*?Tz_CW z#Pq@O(3?}17f%o4fcirEE#Dp5OVip*#>S!z_~KZ9C5r0{b<{nzM!9v8fYku07Bx)G zgMPQ1g3+%ZM@fRk%rDfVuc#h8=*sCWn^Up@4=By(yMqV}h%(IHB~sHrofzd!Bc zra+e+qqzQ2gqeE(9Y+}XEQhIRA({h|z1@#~6H&SDEgY_Whu;{iz`)v1kFfN@yr7?K zZ@@4chuxop3GXWgHq<=}oniWB=Xyz$Q=B}V5Q=5sDkWDsxXc&1uqy^Aapo#;#&~^HaC*!fz>d7@tr!IFz7P$W7?RShwG2@r+tX8%)8P76yfvCb~Kd8PXbs zp#2tpLeRu$n^KcJN6q124ygWN0QL5*5B$%wy1mVpOq~mNOFtrzM^`O{GlpJS%7vJ* zN2L!+P|IbtL72iK8<^Zkg*ydcJY58S&VZS`n>;>1zAx4*(u+#Qz^tIV@LG~aVoyXn zU)A=Q^Zi7MBC47k%J0P66^3tK8rRFzrrou6nb;-Z!W*MYBLNPs@BDN%)MB z!ikrb7tX=X5k!>m7*%GTcvjAvjV|wEbl9=B&#SkdSf?{KnCgqR`EA9Uu1W(`q&dH$<$^89X%5)<1*K#S9q5^DoyQ4 zzHk%+yjdmbW81=aMwwf;#tp4`uZBO6WZ0W@=o!0BEuj@89Cz$dF}o|7o6{gk=pBqt zU@v^a&9MQijZ~O@uj*748LC>`xP-A`vAY#o!5aXqzE=7P4pnlUA{nOBqzPfp1!zyk z9WHf0G|=Ny{B}wZB~&8ga0}kd@6FvoV}2;uJJQI_lSrE9C>u6IoS_5Y6Wi^Paz;`T z4CmEQWfRTBQ!2sTi3r)~bhg*oR-_5dDk7CO;bTM@3OrS3(Y}2!yqF>D^6W>9*u*E) zAnS`AJKwoJRZSj+_i$>ID z_#R)^?4nzYwxDdpr3rEX3laL75+$ws>U(qypz(}K{4e=5VKrZoFE}0T*gmGd;z(Cr zS$aPsX@EnwoW6mcFm4GxfHh7J+`US#M(5Q`s5Mh*%nI=PC}z%JKBH(w&a*c8<6#G# zk!s?Kcww2(ZA#r8(oGZ)3+hPa6HXMiM=c_~GWH)rFa=T_^YXp}JhL|F!o+AF1_7a! z{1o68hLcgcsll~4kjn46Pyx4dIo&3CbDEz(G-d^ zboS?VMiAT@V!EKzxRMFCM&wxJP_47uUKV(7JY#QoxD%wQ1XpJ=c2G6^VbAR9=+z#wi!x)e;6;v>J``+ zd7T&zom9)*?*-3QejN;PKrqF0@dW~PYoaIvP|%vl(%(nca>)VwfYS`6T$j4YUC4KO#sZc95)lFX z{>t_v?)V=Oe-=RlkJ@gg9}6c@I-4_T%VpYH7(IGOR@^U?&sI>|$#ZL>2N(@EkU*?v@hGMmgV$Pp&18p+ax?d) zFL`bpvyhLLOfMwhesU$);tX5&@Vwi#pEeKXS4+HKLC zDJoJbMw?`1_lD3dzVHQmX&uby+`CK)x4;oo1-T&EYyDA4#a5xD->Hr16?ywwNdjB! zuCx{yKBoNsVb5Ji^tEES6j?Xi)P$^bzjQR?CwF6^X0M0YGGE%KSSCMR^w0bW#qg2< zS4I*1^K0;XW33)~oSbnLjEsO0z3v;X1r_~Kmu;h_{gsPr?k|6`(17ekK5aC;{kuRM|Xox=Mz5ZGp$YKFGv&Gl*yG zW`p#ihmZT6L7#e@!O^GgAiXSjsoq#c|MSo(eY##TH9!0V9)_$&%4iNy?)A*u6_P_HqWBRb7JR9Vo9+TjZbTgDn>mZjEfn+a1%bSK!V1h3B&}$MMX#(=+l9|ExnZq+dKI33q3V=7x8NfGk;| zjcv6-PsM}08wt;%AP0-unV$6Id!coE~?Opcxg^T$2gdB}0 zE?nHviE5|tE8WVoqJQP!?C1$)|Gm(l+*7SQAEew=CG(e7K)ZRKCS?3TrX?vpt@s!8 z7@>G}WBB#I{@r?!Vpl|j^#}P30-v4!1@U{N-xz&C`=3z1MEPa0d+B@kQi=OSgq}Es z@!Fm3oNWDHasd*g`9~S~4br7GZ$1&!JlWDr$h{(>6=-K|X7=6YNgBBZ}1rMDcdVC_zi>5}&iGQ1=^GOOA!m z`&C(VbTp@gpObHH8xN=CpPWBD0N^CJ#fqlegxY6spU=_Bro@*MqCZJx^oWj(py$nL zUl$MY9O}ta8OBQ{Z#ND}?!7(7W8^Sf~sBHr9HRkaZ{1A5-H;vZ#mjp%u&A7{r3)eDPJ z#Zw66nzd4nRnXgoCuaS$2F905N!r8p#N9$9ZdfXWWX=wuhO>>ncJxfzjsC>6zVGbe8RS z-wDW0l+@#Ku>Q=l<6H)aHlvgVbxd}JLX@P<-XdyXfh)vP(nK(oLTshW@QV3A+x~nN zmIVgtg5bUbBbRd>c38hDUaO1QLTtZU4=SHj48PI`hBHOUcDV=FqE9C6vlDw4Hd@>e zB^3vW5Nj_$4PVL2g(h|_WCio{sK>7M{bDA`ZPOo=)37l8icb z@-&NEZfg!PdvoeFJQSw$M3-qUsrz!rO#Oz4BFaX-%P4F=Cwm~KZ$65aL19!aT9V8Q z-3It|S-|u;ItG0&8BbTg~5gh9NR)p*^zn(kgr9fnEnVNaCQaa^L&__!vO+rd;deD(8XPr2qODWk6yG*Sh2qDU zm3@8#=s6R0<vg*YTHpv1OUW-6GLwzO!8 zy_m{t7o)Vu;3xuMMCCg0ubKQ@tJbe?za_XHaZk4b_k$=(atb*;m`xg0KhgIvmjjc! zZ&{OTi7!{4iA%`PUcVc>|Jc4CY?WZsy(K;6P3p-ptf)r!5bdTXW2R<9cC-HFQUnTx zNeZH^{&yxeeoVl7hgkaA%={G>mZ0BBM0zL~oBs-gai2wamvRZvTrx@%IpvPelupq2 zkJo7^Nu!Ln0B=ucQ0ByDrXR7~CEj0#HKL3+h}9{(Fj4%z58K_>h;ItCF2AYYiB&8p zDK07OKdbvUK%Wt2aNM{Lf0ZCW)jU#AlX>mOfgch3m;?_Ssmc9jMCM%iO++8q1NNZw^eI znJ84-;O54>t}7<&RXf^q0S?J1G^MND8z`*kxRcN6)pkq^XGg0>q_!XB6NSi(I`LFg zck7Mu9JTh>p^uAo2h!QWRL{kCEv`yzDQeO?7-YAJx`;{1^6|Cow+nYPI{UUM2YXEt zNn@}i+kE9nHu;^b!~-8-KW^WFaEm^>}X9=gr~Stmin})RQbwKarsVhIiWe| z7`c%%fVNv>WD2OtxBCcLunT@Kqh9(2H5R#~F8$d>&mMv3g=f8z(&(R~yOikg>_i|# zQZw4?8jEM9h0C_*&ehbj6-9<6l(A;hZ0TQy$F-nVym{)u2YR;}f`(ZHu^y9zf2djE zEc7~p$QeKVVcw^jfW=d<5y&6beET;=^Guu+)m+h$sXoq%_CzsLIywrV_|qL$D@=Z` z{r?ti{|o%-ytjpZ*!}@x-q>LIgX}OT+ZL3xOZJ|NkGARA zal7y4-~$>?#s38lJF#>(YN$c?-E{sQ4WsT3vt9`4d4SzBArqVt@aYoyuhln|L2?QDq=!@?UvC|K36&8P~nEOiWt z$6AL&Tl#=kTC)VOJ@Eyk2AI^*^$}y^$lm6m^1ch~LR+miRJocg`qFOgzZne;Kt(#E zR9MYcN!-GLVO5QHgd5M~@#us%=~4@|My%k1@x5Y)QBpMr`@&W>4H}zRqf2^FQ|k2! z>x*RQ!MH((X5T4Ykv*7EZ0;p{Gf&nQO}B$F3;yc!vGf!;##c?p*F;tb^i@Q$)cf--Eb$T{*iKtRwS zTf_ipaj@`N?F}`RJ@@dC_RAuE_GX3!ReY|LRmKB|j@0Gc*|c;m&~r%L(Xqnooj(XE z_nOx39I-BN13(Z?{XCHbueI&U?VX*aCyuk$SdhXY)_Z#aLZLHhHwK=n9t#%1nw*n?Eo+N4S zcMWy7f4gwCd2jiP;>-lMY#+FDa$z-jc24p4*?Q%@%05J&ultT4ro(+w^Wj0%=c~T~njt**D()CWEL5kx)MaL65(AH$kS&x*_8jn(DSnoGr0A4J zKX8d})*MJ(f2cM+avLB6d;0+8TvXUt4Ha71c`qiCw_{9~@E{{FEa0tOf~B*(?@#+$m!+loql%vU?b=Yd+Bh9nF4QHosBZ*HqjL zG?mkJE!|bgnnJBJBnw%#hys?7d;Q_O@`!7Jl0R#<&wrBsy(Fjo^rSQLCmj5N`2BaP z1wsl#zxH^D7i;GW0z?e^(+mQ1Wz^n&?%M$b%ObNzD+T_iWY zPr3tp5N0Nv)sM^*+!^9q-^ zfMbixFf~dx&+j%A>bFjZ-UdUgj4Q@S#F;<3q_0Mf5nQ9@rw6aJ#0C;{pyTc*DT01_ zqtryNvVm$oX1<_?$I@GIv4B>D+Xh>V1w#&Gw{yyRy<+n8TIK7w%YM#g;sUG^x%tJtm~+b1_b|srLVHu!pEl&bCe~Vu%l?SU*w{ zIfZyIo-oYpl2^9RRhuyoUfUf@;7Ox8K7S+1Z1Ug8q`$*5siE-*&U*`=Bko21abet3 z`Q(>t^`?2m$U5Kw=^NjM!hIW=mv=Ge=cw^1zZBGU_TGwLHf=AD?*DUu_a0A?Q^_2o z?N!j6fziZxCQF&*9cL9cLG9&dF>Ly%J_-7Fbg+0v7Z3F$6aK0Dc|xjHruay(NKAiZBi7ai#oV7$<&E$Tlnq+3%{lQeJ%f33i zNR`KVAFAiR#oY+|-uq1L?>@rdkMjJG3yJeA+E4UF@N2k}JJHXMGl9c|28^D&ec)Iw zq0e)=8IyNPj0YOGirkmH!vM~Jwy$Bt!rJ>A)3M%4`}FQL;njAcJZ@~}GwlZ^x4Y<^ zW6kv#HPsH7nnOQJy6zQNIPSN_`MP>LfF9XySCcs9#>`*x7jWmwg2yK7nHj%JlJPu?NdYTkebYmmp6hWG&G13Q#VJmjHtRI^D?BjPB|Ca0fv$s zO)eyjA2khA5}ciag5M}x+pN;uW*N?_LI~_+=7_0i=jos$XI#N+Xk= z|9B?7V1oCSEz#*A?bH#{Y#qXUm@Bbu@V>wI0Y9Vl$~9im2J%u#SUXz7$vGUaX9PH+ z!^O|QxH>eBgB5t%eZaMNfi2;dW53_O$q*#)81FUshkx;yE)H&KBi-;~${<;|!vssppD!zf{N^ zEz9;8sQZ=;d!eHp3e5nDf!37#BZ`ufdfPgf=xZx(vuET{{!43-PfT9`G(pprkLaoL zZ6;$RIv4u-3{K_^b<#XQ?tPYq{cUl^hDMg0^YE^31o} zeGuXqdB~Lpn@7+ZLZKq}+p5QB0`r1%Wn8o*P(2D$dA{I~jFAmRye;!G4QQ-+2-GLw zQ7>FSW_WDZmm%C3qI)JvAf*+@F{YOkzHxk+zFks((~6tPwzELgR-XmaQG zx7y{b&08`V7Sgz!AnaTQ+(nL(kx(2nORUARff$Bz(NpA!04+UUrEzXb$`U4;7{le@ z1|5yqcN_dtMj7i&)4J98wmrp{Yd%Xn?T%$-2(*N~UZe>l{c|^p$Aa{G5fO@el&ut| zBVGZ=2aUQs7DYnmp-+Wu=)Tjr2*T<&VWT(i0<3RK@GAtTk~9L`byJT(q&pfZJ2YyO zrLDQTVCnRv9miUHjYcep!e`m`pEVxQx#PpNmr@d8sUghq?|i?eTKS*ln_bSzj?H8u zF>la{HoP^oy1#C1mC<`~EHQgA*w#(M`sJ6y%tLo#kr8nBXfwrW+2$PVx>rh+M_G># z`(3WSc=_^B;-8nR`?!y@_vib&M66i`a@zp*=H1@Ol=471r!b8qxbw77KFa6mHO+{k z#B9oa(pHP?a={0()-Q&K1TwF&!_zkND0Db%u&ij)BVi^^HsJnGqrR^4YipQqQ_AVq z8*QMBCk59X&PqFLDMb{43sGG3y?`FLV@(`qi+KHd-AdK--vG%sl}>l{IjDNyxEsd5 z0w0&>wd*(=yNWr&iaGr9{#GN=sho072x?BW!@N!)bI@U%#M84d?m-gs*% z^ho~3+-`CpQ7NFV!uXh_Am|X}z-*>pmQPS~pB)4}iquD2G<0T&Yu-fNcU}?;y7K%H zvKqtaJC>?dbqm$J(6>lxVA?p%NE6Zh`oG-Fa9`KE`jwSs$fM%-ca+7ZKDT3lbnKIz0xibbAl=ls2G^fL zQl))*MVJ>!#(`#XlL}w6pOAn{qfI4dG~{GvP08jqO+Qk#2gPJbCeip!dDJSX!Z5Ko zM4URLqq~2=5Re0Y9~DD=sZY}dN}^Z&{pM#*FD_*L31?=88vT65Bj}kcNq;2;s_%#o zleFB|E#}S0mJHEqUfp25IqyAuUQ>B7UV>;XefiGszZQq8Bl)+@*!6$e&I!qzC#cMy z@X(L!d4C!xk!?YO3un~iMXY+ZwmK{vl&P3YSk+$YT0$j7Cp9dvRx!-vm7DZKOcS4| zC^Jec-O105s7*3_T_4#wHKVbynS>UXDo?l+Crgk~#n}7Ec0vfGp|+wW_SH>nlDg$n zOg=O3&)kZI;2 zVKts$`b4JN2z<@OC(lr4OKaHKFC>0Kx&WNs)pbxuu1ug^_m2fVT+y5lWZcv-;-UO` zeO7dU)6p#Pm_9v8>1Xy&CRcTv3XsOkb78{FYD&s$+tMiQ`V`z|pB0>>rkQlP-jC-{ zNFwv|Z$L!;e&K(av2B&@i}8xeL*k#^cUWaLhE*hG$|r}Yi20Iv7I#HI?{xe7{)c9% zIt@s+Yu*QwZKWq+Ka6}H-CuhlbAR&O&-zNszg>YZetiAsO-?XPaJj~VO(NZA+vde_ z(D%1rSO2G2Wc(L@g}=Nw>VEd$T%~ettMqdf7ukycqc)jMebjUFUXtdA(3qBv*trpd zm3%|S5~5B`+s!qA+`4nye{!ySDt%7zCv|uIu*Ul3k59vze7#oL96`Qg;ZwJ-Wr@2k zV#?g&egpJgm(FDSyq1xZL3Cy8`%RUN4)JPEG{-2AL(T&_3RbyI$#cHu#ZGLyZtS0~ zzM@MB?%to7o3h`wUggLPP*wTzlV6qXera^bx^c~$!2#1hR*hVmJfZBc4UoOL$dDRk z{7tx{tnD{Sco^mF6u@MPAEfM1Y8;8bR_&dRZT>1+pYx3Gz-;Anr zQsR!_Q;(Gdt$)ZN^;%mD$tdfh>G5iN>jlQ{a)NA(V- z@q>l4Nrvu}~^3 z1bV9Vib5rEYTZIvf-k6B6K&E3GR3Em`o6pLP6z{CgG~fz8NJVDhFSK-QtG-UWN(PL z1x%QE%ImW)yYefJ3>&d~rm?<_I@nH@GZRo?MaWB4Euj@eq(5={@pSSPCl7KIGYQM0 zT*revwa|$h1N8tjt$R5Icb`D#JJltUY+TzQB^Ml0bMk=L>5_YIyZyjaxSJi_>!=Psy&?HBiX^x`h zfi!^CA#?r~>@Z`hSq~o4722q4yztF)$kl4t12K4z;F(6D ze{E|kIa64Cq7uTKQ?_-VB(EnZV+4hS#cAk`0AazQ{e$EJ?urxix3iVMTbYL8tMeW> zvl-4?{t|j@ZtqW(9!#NE?>SAB-@Z<^x-$Xr%Ry(@2gyc}1T)kj_==+<$4x(aP5Uv~ z1UZ&fM|Pt8sGgEb^Xp(@^yRK7e@bXEbmIiA-qZ)7%lsj{Cj46cUc--Coa#qi_IMwj z*1@0^TGgQTgjXO+@+A=%rvmWNE+7iH+$eSpSUiaokm4uAo3N6%xs9fv3#fg)G2ykZ zMB-|^6f7m^?{Z~jH%&#Mr8QoLI({^e&0c)x=}K4RCtb}yM#dq)iDlpiQE{4f6^&5( zPfE6mC7+^ia0)>q!BrSbZY^^fYV%DUcK>_2LDfp?Z)PypToFw@kVK^nE>bCl4tT!d zqA`}rioG_bFFziZ0%~ScYdn~zxnl%3lilS=ZvH+Ui-t#;+Tz8%Q`9IO)^vM;oAEQC zDlx~Om7s7(nExdG} zk58pp_w8Uiz3R9(yvPh{rT_$zpmwTuhidDVxqFgeQwphVY(JoH*$Y1C*XSa!mobZ4 zulI^H@6X}mP9UG}d8JK5LEpP3Z=F~oYJ;}_FuWIUF4-7~z$eo(e4~ov(`51RghpBm zdo(y);M&X#35Gw5|88|q?jLcdM)0D#7$CAy5BTq~dae0aM&(m?tBaIZ#WwTvDmya# zj9Gg$px4B1qaa~+Paom=k;yrw)Xe654t+Vl%Cf68onzG}Z1}b`Je9F0+XeGF^GF#( zQJ1o4p=A*+9q;bREg~*lg-|>!d=F|&!cSQ}Jf)O(UGF0=wGlXeW8kAl0^3+G{g`$b zQz;_G<|#ovYN+`toVJD6w?g!xzkxhr%_Fb+}BqLXy1=1X$Y%ZZ0Wzg>z^4 zSFIknK8apZ>paV4C4PMIew4bt zX*G?=Oy1`_`Ih4RLV*&Ys7>ScrkHBQh-}B0QhRspW+8iVo8a8a{W z4tGT@8K(t`wG?!>JFSvmX<79bRTywJ$_-WBeY9B|h1xh@ksb{*U67r)afxQ3){3N3 zbHI~9C>*;m>1JUM-JZ|Da^%g|_WppMj(_s7HJDK^6iX5@wM{ZMyX2DnhN08h+*cb< zI*!VqQhvhlHd4n$*8rLpN+8Zr_vgMii(S*p2M!~hI<=f))6{#rG|OenJNT(dWm1KC zd@2`z5k$jYwYELys?|aLuR;{Que5X0`mX8(q&4(XYi1V2noYocQLG8}K{)q$&Yv+% zyGAiL?BFTuh*bE6KDacH5JOT_DlQdFhK7jorg&nw^EDv@nR_OMz7$M56dLrU&9PS| z02gZZ1Wq-@H~|`$%QKWI{3QScQzecXgmM@vLebNt)7V3q5}d%HIB$R-m3ZX7&@2gz zPu;*6*#rb4+-eM8hv|^|(maMbvT{1&E%UV!hws3D;Fz!SNjixV*3~-pVckT2X=*yv z-7#LSQjWeft!`U9KeE%bq0x8{0f0VF&>j;KE^Gx%(~+PO^gE2wzU}}xI*pAmj&3Ln z(=1Ou8_qbs6hqk}6^>O=!{GvXh5BIxn-iz^`@aE>+y^+K)jmCB#t&j_J6*j6*uc`r zk0}QeWmd=CMcjf42m%L5rm0)Ex3Q-=ogq?9!73$=bwLj12DES{F@f1!S^3e&PP%M7 z%QOo;0pMP8GGO{y5eZaMD{8j9%1nnMn9_Oapx*$U699mTeO^y|Uy^DDTufr(d5zFd z`mgt&{{eobs!|1Hic3V9By-f{rBqA%J+P>Fly&PoMu?$AJH6zq9FS#akFk;@FZB5G z{rRz;v7z>=Aj$i*ig7VaEF|W)T5b#lzlRP!eW;(>CjK`4@B>}Ll(Jr2{#1kc8kw!k zk0a@vXFisvOIkfV;T*SLD#l;n{f@6}krf%AyY0e$%KZ}NCMz=ghA}JE3(OE%=VYrS$)EMczsUDJl9(k^N_Gk10$j~9@AX;LjO2**Bj>U??R$p zh!*mHN49m5pf%2|)66YA5)YQ{EOtYfpghoP>}P5mLT>a(L{tv2-z}b$%2^G2=&3i+ zwKQyf$%j4`9mZx`4*)+}oED_QT0|+BxuOIrA04+AB}irC!B@%D$9XK`0@vT1u7W$a zQdtkN(I}S&Nf2FQ5;rKG`GOU(pr$(5t%Y^+Q-c~&#%5{}4J}q4Wd7V5>cR);J#blp zSo`O6BhAza!z=c~v23Tv+5vf-g;tjT0gDb(edB3qzc;}~j8)YyUziEdhy4x6XNqJ{ zA(t5_jSU}P%;%&~F0;Z6nKxKyx`lXWF#m$xHr1oi=}`OyeAI{BHwd-`R@lDCmeMay z0Bpz)F;;aH^)tMqN#7g}k<*CtwGnbwBp)#6t-dqta+^I-jtwA7uVr6ap=FvXTO6^) zlIUPsSy3trayO$I`+7o#=xdNhZBV=X850qs&!7OsCV2wT&JE;chRG@*Za+#TDJZ+} z90M5kp4J^{yTp`hijH#W9HaB!J%sH_#N$I8%$Bf=iM@n*x|Ufw39HOtYQ zazB5n;2J$?umU8`{4K=x{Wd}olP*&DB54PAYolFRjnoxw=2fQF(rw9cHP&8ZT1vwg z*004b-#@qoE|F%o~qOT3xkKuxq_M&5^o1RV`Yi9=!piAKq4UrE#fr)hBz zpob1z2_#dj(aQw_+SqVD4A^3Z)Rt}0~yG4uo{ zsXCU7fZu@rm+QEnb;a^YPk$*GDE#0di@WU!T10YTyk#2EZ zZ=V8SDX4=h+77)-2*{`Zx_l<3|eG0MHCXGvW zs{Pmqy~teE#=&UcQbC5Zp!5sTt%9dDbN^+am9lA>j4m~(;mGDLeen(XH3w%CG&4(q zXSU`*;5Je{PufvsZ<-oHqr}YG67~9qvpTqje11)FWR|1Eo}9ps^5>%D?R8}1tib^* zA4uZ3;$xI&lr8ym9Y;&*ZRnko zRs~=b%VU(K8Yum^I}k+2*1NqWI$GeAXl35mx!@>Z!rj3w9KZaAp1P%_%WV$4vn9~$ zs^L~;>c*Y@1&Y8bRiVSo^???lk6Rx|3T2ap4{*Uw}- zJrnCSm-3wcCI0RMU%~?)M^;=j72-)XV50}mAzLwtb=yYALs>P5Do0J3MOmgGh z`uFwJ%+`{lhpMAYX6~*~d4nuwZ!bx@fsBQs=FwVL1QaF4d%^|{CzBxdQHzaFr37_^ z_GUL|KD%z^w6rEKZ@&`H$*KG$?QUbb;`yPODI-W|r-mnD2hmqt^!zNm0J9=u?3`*b zA!{(!IicB0iN!&i+q%r(odprykEH$vuwzVbl*rZ2Onu&QGAH(o1-O*#x}NEXbzpj@ zfrQFP%NNac=V!lu2%0Ed*u0Ye3Eo=m(s^VJeT8iJQsK6?jrLX&NvzD^JXV>M{teLh z=N$92NHyf}m^jl%h$p(nx4Uw_{&@W3Hz4N^_LFSy?G-jvr$7$pV0dRGv4Quci(q2q zLkKsT^(C$%PgJ6}!YGD5(I&jR!Z>pMYTDgf+~59>H(z7Px*0}epBP1$lKO+*J~*2d zluc6nV>CdHNQ8ab3OlVJ)<^$o{wGW{T&tV;j~R*B-+E5;7Am`6qe{8IcYQs*nxe?r z-p|tPx#=O#vPSa*cbZwQl54ubY5%W(+C=ipfHV0g?(Eq!T_^h2a}h@-g+xPz9X+CY gny4iEEAZ<7^Bb;FoB+V!Q{uvb<4(}-@$aSo0jv5YTL1t6 diff --git a/website/site/content/docs/webapp/notify-due-items.png b/website/site/content/docs/webapp/notify-due-items.png deleted file mode 100644 index 10130150cca80ece008879357e350b48a5664094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185940 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