diff --git a/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala index ca727af6..8466ffcc 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/ONotification.scala @@ -255,7 +255,7 @@ object ONotification { r.fold( mail => Channel.Mail(mail.id, mail.connection, Nel.fromListUnsafe(mail.recipients)), - gotify => Channel.Gotify(r.id, gotify.url, gotify.appKey), + gotify => Channel.Gotify(r.id, gotify.url, gotify.appKey, gotify.priority), matrix => Channel.Matrix(r.id, matrix.homeServer, matrix.roomId, matrix.accessToken), http => Channel.Http(r.id, http.url) @@ -296,9 +296,9 @@ object ONotification { time ).vary } yield rec - case Channel.Gotify(_, url, appKey) => + case Channel.Gotify(_, url, appKey, prio) => OptionT.pure[F]( - RNotificationChannelGotify(id, userId, url, appKey, time).vary + RNotificationChannelGotify(id, userId, url, appKey, prio, time).vary ) case Channel.Matrix(_, homeServer, roomId, accessToken) => OptionT.pure[F]( 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 index 5de9250e..8fe34934 100644 --- a/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala +++ b/modules/notification/api/src/main/scala/docspell/notification/api/Channel.scala @@ -53,7 +53,12 @@ object Channel { deriveConfiguredEncoder[Mail] } - final case class Gotify(id: Ident, url: LenientUri, appKey: Password) extends Channel { + final case class Gotify( + id: Ident, + url: LenientUri, + appKey: Password, + priority: Option[Int] + ) extends Channel { val channelType = ChannelType.Gotify def fold[A]( f1: Mail => A, 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 index 5a8d05e2..9eca99f1 100644 --- a/modules/notification/api/src/main/scala/docspell/notification/api/NotificationChannel.scala +++ b/modules/notification/api/src/main/scala/docspell/notification/api/NotificationChannel.scala @@ -30,7 +30,8 @@ object NotificationChannel { headers: Map[String, String] ) extends NotificationChannel - final case class Gotify(url: LenientUri, appKey: Password) extends NotificationChannel + final case class Gotify(url: LenientUri, appKey: Password, priority: Option[Int]) + extends NotificationChannel final case class Matrix( homeServer: LenientUri, 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 index 02415726..da81f6a9 100644 --- a/modules/notification/impl/src/main/scala/docspell/notification/impl/GotifyBackend.scala +++ b/modules/notification/impl/src/main/scala/docspell/notification/impl/GotifyBackend.scala @@ -35,6 +35,7 @@ final class GotifyBackend[F[_]: Async]( val req = POST( Json.obj( "title" -> Json.fromString(title), + "priority" -> Json.fromInt(channel.priority.getOrElse(0)), "message" -> Json.fromString(body), "extras" -> Json.obj( "client::display" -> Json.obj( diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml index 135fa85e..04e3c6f0 100644 --- a/modules/restapi/src/main/resources/docspell-openapi.yml +++ b/modules/restapi/src/main/resources/docspell-openapi.yml @@ -5523,6 +5523,11 @@ components: appKey: type: string format: password + priority: + type: integer + format: int32 + description: | + A priority number [0-10] NotificationHttp: description: | A notification channel for receiving a generic http request. diff --git a/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala index 843fb17a..7c6c1021 100644 --- a/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala +++ b/modules/restapi/src/main/scala/docspell/restapi/model/NotificationChannel.scala @@ -74,7 +74,8 @@ object NotificationChannel { .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)), + gotify => + Right(Channel.Gotify(gotify.id, gotify.url, gotify.appKey, gotify.priority)), matrix => Right( Channel @@ -94,7 +95,8 @@ object NotificationChannel { m.recipients.toList.map(_.displayString) ) }, - g => gotify(NotificationGotify(g.id, ChannelType.Gotify, g.url, g.appKey)), + g => + gotify(NotificationGotify(g.id, ChannelType.Gotify, g.url, g.appKey, g.priority)), m => matrix( NotificationMatrix( diff --git a/modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala b/modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala index e288b3d1..32052466 100644 --- a/modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala +++ b/modules/restapi/src/test/scala/docspell/restapi/model/NotificationCodecTest.scala @@ -53,7 +53,34 @@ class NotificationCodecTest extends FunSuite { id(""), ChannelType.Gotify, LenientUri.unsafe("http://test.gotify.com"), - Password("abcde") + Password("abcde"), + None + ) + ) + ) + ) + } + + test("decode with gotify data with prio") { + val json = """{"id":"", + "enabled": true, + "channel": {"id":"", "channelType":"gotify", "url":"http://test.gotify.com", "appKey": "abcde", "priority":9}, + "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"), + Some(9) ) ) ) diff --git a/modules/store/src/main/resources/db/migration/h2/V1.31.1__gotify_prio.sql b/modules/store/src/main/resources/db/migration/h2/V1.31.1__gotify_prio.sql new file mode 100644 index 00000000..d4c05406 --- /dev/null +++ b/modules/store/src/main/resources/db/migration/h2/V1.31.1__gotify_prio.sql @@ -0,0 +1,2 @@ +ALTER TABLE "notification_channel_gotify" +ADD COLUMN "priority" integer; diff --git a/modules/store/src/main/resources/db/migration/mariadb/V1.31.1__gotify_prio.sql b/modules/store/src/main/resources/db/migration/mariadb/V1.31.1__gotify_prio.sql new file mode 100644 index 00000000..d61ab681 --- /dev/null +++ b/modules/store/src/main/resources/db/migration/mariadb/V1.31.1__gotify_prio.sql @@ -0,0 +1,2 @@ +ALTER TABLE `notification_channel_gotify` +ADD COLUMN `priority` tinyint unsigned; diff --git a/modules/store/src/main/resources/db/migration/postgresql/V1.31.1__gotify_prio.sql b/modules/store/src/main/resources/db/migration/postgresql/V1.31.1__gotify_prio.sql new file mode 100644 index 00000000..6374f53a --- /dev/null +++ b/modules/store/src/main/resources/db/migration/postgresql/V1.31.1__gotify_prio.sql @@ -0,0 +1,2 @@ +ALTER TABLE "notification_channel_gotify" +ADD COLUMN "priority" smallint; diff --git a/modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala b/modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala index 44501ee8..f04a4c8c 100644 --- a/modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala +++ b/modules/store/src/main/scala/docspell/store/queries/ChannelMap.scala @@ -26,7 +26,7 @@ object ChannelMap { def readGotify( r: RNotificationChannelGotify ): ConnectionIO[Vector[NotificationChannel]] = - pure(NotificationChannel.Gotify(r.url, r.appKey)) + pure(NotificationChannel.Gotify(r.url, r.appKey, r.priority)) def readMatrix( r: RNotificationChannelMatrix diff --git a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala index 115da0ed..4464f5f0 100644 --- a/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala +++ b/modules/store/src/main/scala/docspell/store/records/RNotificationChannelGotify.scala @@ -20,6 +20,7 @@ final case class RNotificationChannelGotify( uid: Ident, url: LenientUri, appKey: Password, + priority: Option[Int], created: Timestamp ) { def vary: RNotificationChannel = @@ -35,10 +36,11 @@ object RNotificationChannelGotify { val uid = Column[Ident]("uid", this) val url = Column[LenientUri]("url", this) val appKey = Column[Password]("app_key", this) + val priority = Column[Int]("priority", this) val created = Column[Timestamp]("created", this) val all: NonEmptyList[Column[_]] = - NonEmptyList.of(id, uid, url, appKey, created) + NonEmptyList.of(id, uid, url, appKey, priority, created) } val T: Table = Table(None) @@ -49,7 +51,11 @@ object 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}") + DML.insert( + T, + T.all, + sql"${r.id},${r.uid},${r.url},${r.appKey},${r.priority},${r.created}" + ) def update(r: RNotificationChannelGotify): ConnectionIO[Int] = DML.update( @@ -57,7 +63,8 @@ object RNotificationChannelGotify { T.id === r.id && T.uid === r.uid, DML.set( T.url.setTo(r.url), - T.appKey.setTo(r.appKey) + T.appKey.setTo(r.appKey), + T.priority.setTo(r.priority) ) ) diff --git a/modules/webapp/src/main/elm/Comp/IntField.elm b/modules/webapp/src/main/elm/Comp/IntField.elm index eaab9e81..b2ec897f 100644 --- a/modules/webapp/src/main/elm/Comp/IntField.elm +++ b/modules/webapp/src/main/elm/Comp/IntField.elm @@ -149,16 +149,3 @@ view cfg model = [ Maybe.withDefault "" model.error |> text ] ] - - -viewWithInfo2 : String -> String -> Maybe Int -> String -> Model -> Html Msg -viewWithInfo2 label info nval classes model = - let - cfg = - { label = label - , info = info - , number = nval - , classes = classes - } - in - view cfg model diff --git a/modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm b/modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm index ffcf9d73..83454297 100644 --- a/modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm +++ b/modules/webapp/src/main/elm/Comp/NotificationGotifyForm.elm @@ -9,6 +9,8 @@ module Comp.NotificationGotifyForm exposing (Model, Msg, init, initWith, update, import Api.Model.NotificationGotify exposing (NotificationGotify) import Comp.Basic as B +import Comp.FixedDropdown +import Data.DropdownStyle import Data.NotificationChannel import Html exposing (..) import Html.Attributes exposing (..) @@ -19,24 +21,28 @@ import Styles as S type alias Model = { hook : NotificationGotify + , prioModel : Comp.FixedDropdown.Model Int } init : Model init = { hook = Data.NotificationChannel.setTypeGotify Api.Model.NotificationGotify.empty + , prioModel = Comp.FixedDropdown.init (List.range 0 10) } initWith : NotificationGotify -> Model initWith hook = { hook = Data.NotificationChannel.setTypeGotify hook + , prioModel = Comp.FixedDropdown.init (List.range 0 10) } type Msg = SetUrl String | SetAppKey String + | PrioMsg (Comp.FixedDropdown.Msg Int) @@ -46,10 +52,25 @@ type Msg update : Msg -> Model -> ( Model, Maybe NotificationGotify ) update msg model = let - newHook = - updateHook msg model.hook + hook = + model.hook + + newModel = + case msg of + SetUrl s -> + { model | hook = { hook | url = s } } + + SetAppKey s -> + { model | hook = { hook | appKey = s } } + + PrioMsg lm -> + let + ( m, sel ) = + Comp.FixedDropdown.update lm model.prioModel + in + { model | hook = { hook | priority = sel }, prioModel = m } in - ( { model | hook = newHook }, check newHook ) + ( newModel, check newModel.hook ) check : NotificationGotify -> Maybe NotificationGotify @@ -57,22 +78,20 @@ 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 = + let + cfg = + { display = String.fromInt + , icon = \n -> Nothing + , selectPlaceholder = texts.priority + , style = Data.DropdownStyle.mainStyle + } + in div [] [ div [ class "mb-2" @@ -114,4 +133,18 @@ view texts model = ] [] ] + , div + [ class "mb-2" + ] + [ label + [ for "prio" + , class S.inputLabel + ] + [ text texts.priority + ] + , Html.map PrioMsg (Comp.FixedDropdown.viewStyled2 cfg False model.hook.priority model.prioModel) + , span [ class "text-sm opacity-75" ] + [ text texts.priorityInfo + ] + ] ] diff --git a/modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm b/modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm index 329bf483..4a6afb30 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/NotificationGotifyForm.elm @@ -18,6 +18,8 @@ type alias Texts = { basics : Messages.Basics.Texts , gotifyUrl : String , appKey : String + , priority : String + , priorityInfo : String } @@ -26,6 +28,8 @@ gb = { basics = Messages.Basics.gb , gotifyUrl = "Gotify URL" , appKey = "App Key" + , priority = "Priority" + , priorityInfo = "A number denoting the importance of a message controlling notification behaviour. The higher the more important." } @@ -34,4 +38,6 @@ de = { basics = Messages.Basics.de , gotifyUrl = "Gotify URL" , appKey = "App Key" + , priority = "Priorität" + , priorityInfo = "Eine Zahl, um die Wichtigkeit anzugeben (je höher desto wichtiger). Es steuert, wie eine Notifizierung erscheint." }