mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-05 22:55:58 +00:00
Improve form
This commit is contained in:
parent
5a2e28415a
commit
3a90d874a5
@ -15,6 +15,10 @@ trait OTag[F[_]] {
|
|||||||
def update(s: RTag): F[AddResult]
|
def update(s: RTag): F[AddResult]
|
||||||
|
|
||||||
def delete(id: Ident, collective: Ident): F[AddResult]
|
def delete(id: Ident, collective: Ident): F[AddResult]
|
||||||
|
|
||||||
|
/** Load all tags given their ids. Ids that are not available are ignored.
|
||||||
|
*/
|
||||||
|
def loadAll(ids: List[Ident]): F[Vector[RTag]]
|
||||||
}
|
}
|
||||||
|
|
||||||
object OTag {
|
object OTag {
|
||||||
@ -48,5 +52,9 @@ object OTag {
|
|||||||
} yield n0.getOrElse(0) + n1.getOrElse(0)
|
} yield n0.getOrElse(0) + n1.getOrElse(0)
|
||||||
store.transact(io).attempt.map(AddResult.fromUpdate)
|
store.transact(io).attempt.map(AddResult.fromUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def loadAll(ids: List[Ident]): F[Vector[RTag]] =
|
||||||
|
if (ids.isEmpty) Vector.empty.pure[F]
|
||||||
|
else store.transact(RTag.findAllById(ids))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1597,7 +1597,7 @@ paths:
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/NotificationData"
|
$ref: "#/components/schemas/NotificationSettings"
|
||||||
post:
|
post:
|
||||||
tags: [ Notification ]
|
tags: [ Notification ]
|
||||||
summary: Change current settings for "Notify Due Items" task
|
summary: Change current settings for "Notify Due Items" task
|
||||||
@ -1683,27 +1683,11 @@ components:
|
|||||||
tagsInclude:
|
tagsInclude:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
$ref: "#/components/schemas/Tag"
|
||||||
format: ident
|
|
||||||
tagsExclude:
|
tagsExclude:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
$ref: "#/components/schemas/Tag"
|
||||||
format: ident
|
|
||||||
NotificationData:
|
|
||||||
description: |
|
|
||||||
Data for the notification settings.
|
|
||||||
required:
|
|
||||||
- settings
|
|
||||||
properties:
|
|
||||||
settings:
|
|
||||||
$ref: "#/components/schemas/NotificationSettings"
|
|
||||||
nextRun:
|
|
||||||
type: integer
|
|
||||||
format: date-time
|
|
||||||
lastRun:
|
|
||||||
type: integer
|
|
||||||
format: date-time
|
|
||||||
SentMails:
|
SentMails:
|
||||||
description: |
|
description: |
|
||||||
A list of sent mails.
|
A list of sent mails.
|
||||||
|
@ -25,7 +25,8 @@ object NotifyDueItemsRoutes {
|
|||||||
case GET -> Root =>
|
case GET -> Root =>
|
||||||
for {
|
for {
|
||||||
task <- ut.getNotifyDueItems(user.account)
|
task <- ut.getNotifyDueItems(user.account)
|
||||||
resp <- Ok(convert(task))
|
res <- taskToSettings(user.account, backend, task)
|
||||||
|
resp <- Ok(res)
|
||||||
} yield resp
|
} yield resp
|
||||||
|
|
||||||
case req @ POST -> Root =>
|
case req @ POST -> Root =>
|
||||||
@ -41,9 +42,6 @@ object NotifyDueItemsRoutes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def convert(task: UserTask[NotifyDueItemsArgs]): NotificationData =
|
|
||||||
NotificationData(taskToSettings(task), None, None)
|
|
||||||
|
|
||||||
def makeTask(
|
def makeTask(
|
||||||
user: AccountId,
|
user: AccountId,
|
||||||
settings: NotificationSettings
|
settings: NotificationSettings
|
||||||
@ -58,20 +56,34 @@ object NotifyDueItemsRoutes {
|
|||||||
settings.smtpConnection,
|
settings.smtpConnection,
|
||||||
settings.recipients,
|
settings.recipients,
|
||||||
settings.remindDays,
|
settings.remindDays,
|
||||||
settings.tagsInclude.map(Ident.unsafe),
|
settings.tagsInclude.map(_.id),
|
||||||
settings.tagsExclude.map(Ident.unsafe)
|
settings.tagsExclude.map(_.id)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def taskToSettings(task: UserTask[NotifyDueItemsArgs]): NotificationSettings =
|
// TODO this should be inside the backend code and not here
|
||||||
NotificationSettings(
|
def taskToSettings[F[_]: Sync](
|
||||||
|
account: AccountId,
|
||||||
|
backend: BackendApp[F],
|
||||||
|
task: UserTask[NotifyDueItemsArgs]
|
||||||
|
): F[NotificationSettings] =
|
||||||
|
for {
|
||||||
|
tinc <- backend.tag.loadAll(task.args.tagsInclude)
|
||||||
|
texc <- backend.tag.loadAll(task.args.tagsExclude)
|
||||||
|
conn <- backend.mail
|
||||||
|
.getSettings(account, None)
|
||||||
|
.map(
|
||||||
|
_.find(_.name == task.args.smtpConnection)
|
||||||
|
.map(_.name)
|
||||||
|
)
|
||||||
|
} yield NotificationSettings(
|
||||||
task.id,
|
task.id,
|
||||||
task.enabled,
|
task.enabled,
|
||||||
task.args.smtpConnection,
|
conn.getOrElse(Ident.unsafe("none")),
|
||||||
task.args.recipients,
|
task.args.recipients,
|
||||||
task.timer,
|
task.timer,
|
||||||
task.args.remindDays,
|
task.args.remindDays,
|
||||||
task.args.tagsInclude.map(_.id),
|
tinc.map(Conversions.mkTag).toList,
|
||||||
task.args.tagsExclude.map(_.id)
|
texc.map(Conversions.mkTag).toList
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,11 @@ object RTag {
|
|||||||
sql.query[RTag].to[Vector]
|
sql.query[RTag].to[Vector]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def findAllById(ids: List[Ident]): ConnectionIO[Vector[RTag]] =
|
||||||
|
selectSimple(all, table, tid.isIn(ids.map(id => sql"$id").toSeq))
|
||||||
|
.query[RTag]
|
||||||
|
.to[Vector]
|
||||||
|
|
||||||
def findByItem(itemId: Ident): ConnectionIO[Vector[RTag]] = {
|
def findByItem(itemId: Ident): ConnectionIO[Vector[RTag]] = {
|
||||||
val rcol = all.map(_.prefix("t"))
|
val rcol = all.map(_.prefix("t"))
|
||||||
(selectSimple(
|
(selectSimple(
|
||||||
|
@ -21,6 +21,7 @@ module Api exposing
|
|||||||
, getJobQueueState
|
, getJobQueueState
|
||||||
, getJobQueueStateIn
|
, getJobQueueStateIn
|
||||||
, getMailSettings
|
, getMailSettings
|
||||||
|
, getNotifyDueItems
|
||||||
, getOrgLight
|
, getOrgLight
|
||||||
, getOrganizations
|
, getOrganizations
|
||||||
, getPersons
|
, getPersons
|
||||||
@ -85,6 +86,7 @@ import Api.Model.ItemProposals exposing (ItemProposals)
|
|||||||
import Api.Model.ItemSearch exposing (ItemSearch)
|
import Api.Model.ItemSearch exposing (ItemSearch)
|
||||||
import Api.Model.ItemUploadMeta exposing (ItemUploadMeta)
|
import Api.Model.ItemUploadMeta exposing (ItemUploadMeta)
|
||||||
import Api.Model.JobQueueState exposing (JobQueueState)
|
import Api.Model.JobQueueState exposing (JobQueueState)
|
||||||
|
import Api.Model.NotificationSettings exposing (NotificationSettings)
|
||||||
import Api.Model.OptionalDate exposing (OptionalDate)
|
import Api.Model.OptionalDate exposing (OptionalDate)
|
||||||
import Api.Model.OptionalId exposing (OptionalId)
|
import Api.Model.OptionalId exposing (OptionalId)
|
||||||
import Api.Model.OptionalText exposing (OptionalText)
|
import Api.Model.OptionalText exposing (OptionalText)
|
||||||
@ -117,6 +119,22 @@ import Util.Http as Http2
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- NotifyDueItems
|
||||||
|
|
||||||
|
|
||||||
|
getNotifyDueItems :
|
||||||
|
Flags
|
||||||
|
-> (Result Http.Error NotificationSettings -> 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.NotificationSettings.decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- CalEvent
|
--- CalEvent
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ module Comp.CalEventInput exposing
|
|||||||
( Model
|
( Model
|
||||||
, Msg
|
, Msg
|
||||||
, init
|
, init
|
||||||
, initialSchedule
|
|
||||||
, update
|
, update
|
||||||
, view
|
, view
|
||||||
)
|
)
|
||||||
@ -10,7 +9,9 @@ module Comp.CalEventInput exposing
|
|||||||
import Api
|
import Api
|
||||||
import Api.Model.CalEventCheck exposing (CalEventCheck)
|
import Api.Model.CalEventCheck exposing (CalEventCheck)
|
||||||
import Api.Model.CalEventCheckResult exposing (CalEventCheckResult)
|
import Api.Model.CalEventCheckResult exposing (CalEventCheckResult)
|
||||||
|
import Data.CalEvent exposing (CalEvent)
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.Validated exposing (Validated(..))
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onInput)
|
import Html.Events exposing (onInput)
|
||||||
@ -21,14 +22,7 @@ import Util.Time
|
|||||||
|
|
||||||
|
|
||||||
type alias Model =
|
type alias Model =
|
||||||
{ year : String
|
{ checkResult : Maybe CalEventCheckResult
|
||||||
, month : String
|
|
||||||
, day : String
|
|
||||||
, hour : String
|
|
||||||
, minute : String
|
|
||||||
, weekday : Maybe String
|
|
||||||
, event : Maybe String
|
|
||||||
, checkResult : Maybe CalEventCheckResult
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -39,68 +33,29 @@ type Msg
|
|||||||
| SetHour String
|
| SetHour String
|
||||||
| SetMinute String
|
| SetMinute String
|
||||||
| SetWeekday String
|
| SetWeekday String
|
||||||
| CheckInputMsg (Result Http.Error CalEventCheckResult)
|
| CheckInputMsg CalEvent (Result Http.Error CalEventCheckResult)
|
||||||
|
|
||||||
|
|
||||||
initialSchedule : String
|
init : Flags -> CalEvent -> ( Model, Cmd Msg )
|
||||||
initialSchedule =
|
init flags ev =
|
||||||
"*-*-01 00:00"
|
( Model Nothing, checkInput flags ev )
|
||||||
|
|
||||||
|
|
||||||
init : Flags -> ( Model, Cmd Msg )
|
checkInput : Flags -> CalEvent -> Cmd Msg
|
||||||
init flags =
|
checkInput flags ev =
|
||||||
let
|
let
|
||||||
model =
|
eventStr =
|
||||||
{ year = "*"
|
Data.CalEvent.makeEvent ev
|
||||||
, month = "*"
|
|
||||||
, day = "1"
|
|
||||||
, hour = "0"
|
|
||||||
, minute = "0"
|
|
||||||
, weekday = Nothing
|
|
||||||
, event = Nothing
|
|
||||||
, checkResult = Nothing
|
|
||||||
}
|
|
||||||
in
|
|
||||||
( model, checkInput flags model )
|
|
||||||
|
|
||||||
|
|
||||||
toEvent : Model -> String
|
|
||||||
toEvent model =
|
|
||||||
let
|
|
||||||
datetime =
|
|
||||||
model.year
|
|
||||||
++ "-"
|
|
||||||
++ model.month
|
|
||||||
++ "-"
|
|
||||||
++ model.day
|
|
||||||
++ " "
|
|
||||||
++ model.hour
|
|
||||||
++ ":"
|
|
||||||
++ model.minute
|
|
||||||
in
|
|
||||||
case model.weekday of
|
|
||||||
Just wd ->
|
|
||||||
wd ++ " " ++ datetime
|
|
||||||
|
|
||||||
Nothing ->
|
|
||||||
datetime
|
|
||||||
|
|
||||||
|
|
||||||
checkInput : Flags -> Model -> Cmd Msg
|
|
||||||
checkInput flags model =
|
|
||||||
let
|
|
||||||
event =
|
|
||||||
toEvent model
|
|
||||||
|
|
||||||
input =
|
input =
|
||||||
CalEventCheck event
|
CalEventCheck eventStr
|
||||||
in
|
in
|
||||||
Api.checkCalEvent flags input CheckInputMsg
|
Api.checkCalEvent flags input (CheckInputMsg ev)
|
||||||
|
|
||||||
|
|
||||||
withCheckInput : Flags -> Model -> ( Model, Cmd Msg, Maybe String )
|
withCheckInput : Flags -> CalEvent -> Model -> ( Model, Cmd Msg, Validated CalEvent )
|
||||||
withCheckInput flags model =
|
withCheckInput flags ev model =
|
||||||
( model, checkInput flags model, Nothing )
|
( model, checkInput flags ev, Unknown ev )
|
||||||
|
|
||||||
|
|
||||||
isCheckError : Model -> Bool
|
isCheckError : Model -> Bool
|
||||||
@ -110,46 +65,49 @@ isCheckError model =
|
|||||||
|> not
|
|> not
|
||||||
|
|
||||||
|
|
||||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Maybe String )
|
update : Flags -> CalEvent -> Msg -> Model -> ( Model, Cmd Msg, Validated CalEvent )
|
||||||
update flags msg model =
|
update flags ev msg model =
|
||||||
case msg of
|
case msg of
|
||||||
SetYear str ->
|
SetYear str ->
|
||||||
withCheckInput flags { model | year = str }
|
withCheckInput flags { ev | year = str } model
|
||||||
|
|
||||||
SetMonth str ->
|
SetMonth str ->
|
||||||
withCheckInput flags { model | month = str }
|
withCheckInput flags { ev | month = str } model
|
||||||
|
|
||||||
SetDay str ->
|
SetDay str ->
|
||||||
withCheckInput flags { model | day = str }
|
withCheckInput flags { ev | day = str } model
|
||||||
|
|
||||||
SetHour str ->
|
SetHour str ->
|
||||||
withCheckInput flags { model | hour = str }
|
withCheckInput flags { ev | hour = str } model
|
||||||
|
|
||||||
SetMinute str ->
|
SetMinute str ->
|
||||||
withCheckInput flags { model | minute = str }
|
withCheckInput flags { ev | minute = str } model
|
||||||
|
|
||||||
SetWeekday str ->
|
SetWeekday str ->
|
||||||
withCheckInput flags { model | weekday = Util.Maybe.fromString str }
|
withCheckInput flags { ev | weekday = Util.Maybe.fromString str } model
|
||||||
|
|
||||||
CheckInputMsg (Ok res) ->
|
CheckInputMsg event (Ok res) ->
|
||||||
let
|
let
|
||||||
m =
|
m =
|
||||||
{ model
|
{ model | checkResult = Just res }
|
||||||
| event = res.event
|
|
||||||
, checkResult = Just res
|
|
||||||
}
|
|
||||||
in
|
in
|
||||||
( m, Cmd.none, res.event )
|
( m
|
||||||
|
, Cmd.none
|
||||||
|
, if res.success then
|
||||||
|
Valid event
|
||||||
|
|
||||||
CheckInputMsg (Err err) ->
|
else
|
||||||
|
Invalid event
|
||||||
|
)
|
||||||
|
|
||||||
|
CheckInputMsg event (Err err) ->
|
||||||
let
|
let
|
||||||
emptyResult =
|
emptyResult =
|
||||||
Api.Model.CalEventCheckResult.empty
|
Api.Model.CalEventCheckResult.empty
|
||||||
|
|
||||||
m =
|
m =
|
||||||
{ model
|
{ model
|
||||||
| event = Nothing
|
| checkResult =
|
||||||
, checkResult =
|
|
||||||
Just
|
Just
|
||||||
{ emptyResult
|
{ emptyResult
|
||||||
| success = False
|
| success = False
|
||||||
@ -157,14 +115,14 @@ update flags msg model =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
in
|
in
|
||||||
( m, Cmd.none, Nothing )
|
( m, Cmd.none, Unknown event )
|
||||||
|
|
||||||
|
|
||||||
view : String -> Model -> Html Msg
|
view : String -> CalEvent -> Model -> Html Msg
|
||||||
view extraClasses model =
|
view extraClasses ev model =
|
||||||
let
|
let
|
||||||
yearLen =
|
yearLen =
|
||||||
Basics.max 4 (String.length model.year)
|
Basics.max 4 (String.length ev.year)
|
||||||
|
|
||||||
otherLen str =
|
otherLen str =
|
||||||
Basics.max 2 (String.length str)
|
Basics.max 2 (String.length str)
|
||||||
@ -181,10 +139,10 @@ view extraClasses model =
|
|||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, class "time-input"
|
, class "time-input"
|
||||||
, size
|
, size
|
||||||
(Maybe.map otherLen model.weekday
|
(Maybe.map otherLen ev.weekday
|
||||||
|> Maybe.withDefault 4
|
|> Maybe.withDefault 4
|
||||||
)
|
)
|
||||||
, Maybe.withDefault "" model.weekday
|
, Maybe.withDefault "" ev.weekday
|
||||||
|> value
|
|> value
|
||||||
, onInput SetWeekday
|
, onInput SetWeekday
|
||||||
]
|
]
|
||||||
@ -196,7 +154,7 @@ view extraClasses model =
|
|||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, class "time-input"
|
, class "time-input"
|
||||||
, size yearLen
|
, size yearLen
|
||||||
, value model.year
|
, value ev.year
|
||||||
, onInput SetYear
|
, onInput SetYear
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
@ -209,8 +167,8 @@ view extraClasses model =
|
|||||||
, input
|
, input
|
||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, class "time-input"
|
, class "time-input"
|
||||||
, size (otherLen model.month)
|
, size (otherLen ev.month)
|
||||||
, value model.month
|
, value ev.month
|
||||||
, onInput SetMonth
|
, onInput SetMonth
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
@ -223,8 +181,8 @@ view extraClasses model =
|
|||||||
, input
|
, input
|
||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, class "time-input"
|
, class "time-input"
|
||||||
, size (otherLen model.day)
|
, size (otherLen ev.day)
|
||||||
, value model.day
|
, value ev.day
|
||||||
, onInput SetDay
|
, onInput SetDay
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
@ -237,8 +195,8 @@ view extraClasses model =
|
|||||||
, input
|
, input
|
||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, class "time-input"
|
, class "time-input"
|
||||||
, size (otherLen model.hour)
|
, size (otherLen ev.hour)
|
||||||
, value model.hour
|
, value ev.hour
|
||||||
, onInput SetHour
|
, onInput SetHour
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
@ -251,8 +209,8 @@ view extraClasses model =
|
|||||||
, input
|
, input
|
||||||
[ type_ "text"
|
[ type_ "text"
|
||||||
, class "time-input"
|
, class "time-input"
|
||||||
, size (otherLen model.minute)
|
, size (otherLen ev.minute)
|
||||||
, value model.minute
|
, value ev.minute
|
||||||
, onInput SetMinute
|
, onInput SetMinute
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
|
@ -15,7 +15,9 @@ import Comp.CalEventInput
|
|||||||
import Comp.Dropdown
|
import Comp.Dropdown
|
||||||
import Comp.EmailInput
|
import Comp.EmailInput
|
||||||
import Comp.IntField
|
import Comp.IntField
|
||||||
|
import Data.CalEvent exposing (CalEvent)
|
||||||
import Data.Flags exposing (Flags)
|
import Data.Flags exposing (Flags)
|
||||||
|
import Data.Validated exposing (Validated)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
import Html.Events exposing (onCheck, onClick)
|
import Html.Events exposing (onCheck, onClick)
|
||||||
@ -35,7 +37,7 @@ type alias Model =
|
|||||||
, remindDays : Maybe Int
|
, remindDays : Maybe Int
|
||||||
, remindDaysModel : Comp.IntField.Model
|
, remindDaysModel : Comp.IntField.Model
|
||||||
, enabled : Bool
|
, enabled : Bool
|
||||||
, schedule : String
|
, schedule : Validated CalEvent
|
||||||
, scheduleModel : Comp.CalEventInput.Model
|
, scheduleModel : Comp.CalEventInput.Model
|
||||||
, formError : Maybe String
|
, formError : Maybe String
|
||||||
}
|
}
|
||||||
@ -52,6 +54,7 @@ type Msg
|
|||||||
| RemindDaysMsg Comp.IntField.Msg
|
| RemindDaysMsg Comp.IntField.Msg
|
||||||
| ToggleEnabled
|
| ToggleEnabled
|
||||||
| CalEventMsg Comp.CalEventInput.Msg
|
| CalEventMsg Comp.CalEventInput.Msg
|
||||||
|
| SetNotificationSettings (Result Http.Error NotificationSettings)
|
||||||
|
|
||||||
|
|
||||||
initCmd : Flags -> Cmd Msg
|
initCmd : Flags -> Cmd Msg
|
||||||
@ -59,14 +62,18 @@ initCmd flags =
|
|||||||
Cmd.batch
|
Cmd.batch
|
||||||
[ Api.getMailSettings flags "" ConnResp
|
[ Api.getMailSettings flags "" ConnResp
|
||||||
, Api.getTags flags "" GetTagsResp
|
, Api.getTags flags "" GetTagsResp
|
||||||
|
, Api.getNotifyDueItems flags SetNotificationSettings
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
init : Flags -> ( Model, Cmd Msg )
|
init : Flags -> ( Model, Cmd Msg )
|
||||||
init flags =
|
init flags =
|
||||||
let
|
let
|
||||||
|
initialSchedule =
|
||||||
|
Data.Validated.Unknown Data.CalEvent.everyMonth
|
||||||
|
|
||||||
( sm, sc ) =
|
( sm, sc ) =
|
||||||
Comp.CalEventInput.init flags
|
Comp.CalEventInput.init flags Data.CalEvent.everyMonth
|
||||||
in
|
in
|
||||||
( { settings = Api.Model.NotificationSettings.empty
|
( { settings = Api.Model.NotificationSettings.empty
|
||||||
, connectionModel =
|
, connectionModel =
|
||||||
@ -81,7 +88,7 @@ init flags =
|
|||||||
, remindDays = Just 1
|
, remindDays = Just 1
|
||||||
, remindDaysModel = Comp.IntField.init (Just 1) Nothing True "Remind Days"
|
, remindDaysModel = Comp.IntField.init (Just 1) Nothing True "Remind Days"
|
||||||
, enabled = False
|
, enabled = False
|
||||||
, schedule = Comp.CalEventInput.initialSchedule
|
, schedule = initialSchedule
|
||||||
, scheduleModel = sm
|
, scheduleModel = sm
|
||||||
, formError = Nothing
|
, formError = Nothing
|
||||||
}
|
}
|
||||||
@ -98,10 +105,13 @@ update flags msg model =
|
|||||||
CalEventMsg lmsg ->
|
CalEventMsg lmsg ->
|
||||||
let
|
let
|
||||||
( cm, cc, cs ) =
|
( cm, cc, cs ) =
|
||||||
Comp.CalEventInput.update flags lmsg model.scheduleModel
|
Comp.CalEventInput.update flags
|
||||||
|
(Data.Validated.value model.schedule)
|
||||||
|
lmsg
|
||||||
|
model.scheduleModel
|
||||||
in
|
in
|
||||||
( { model
|
( { model
|
||||||
| schedule = Maybe.withDefault model.schedule cs
|
| schedule = cs
|
||||||
, scheduleModel = cm
|
, scheduleModel = cm
|
||||||
}
|
}
|
||||||
, Cmd.map CalEventMsg cc
|
, Cmd.map CalEventMsg cc
|
||||||
@ -141,7 +151,7 @@ update flags msg model =
|
|||||||
| connectionModel = cm
|
| connectionModel = cm
|
||||||
, formError =
|
, formError =
|
||||||
if names == [] then
|
if names == [] then
|
||||||
Just "No E-Mail connections configured. Goto user settings to add one."
|
Just "No E-Mail connections configured. Goto E-Mail Settings to add one."
|
||||||
|
|
||||||
else
|
else
|
||||||
Nothing
|
Nothing
|
||||||
@ -199,7 +209,40 @@ update flags msg model =
|
|||||||
ToggleEnabled ->
|
ToggleEnabled ->
|
||||||
( { model | enabled = not model.enabled }, Cmd.none )
|
( { model | enabled = not model.enabled }, Cmd.none )
|
||||||
|
|
||||||
_ ->
|
SetNotificationSettings (Ok s) ->
|
||||||
|
let
|
||||||
|
( nm, nc ) =
|
||||||
|
Util.Update.andThen1
|
||||||
|
[ update flags (ConnMsg (Comp.Dropdown.SetSelection [ s.smtpConnection ]))
|
||||||
|
, update flags (TagIncMsg (Comp.Dropdown.SetSelection s.tagsInclude))
|
||||||
|
, update flags (TagExcMsg (Comp.Dropdown.SetSelection s.tagsExclude))
|
||||||
|
]
|
||||||
|
model
|
||||||
|
|
||||||
|
newSchedule =
|
||||||
|
Data.CalEvent.fromEvent s.schedule
|
||||||
|
|> Maybe.withDefault Data.CalEvent.everyMonth
|
||||||
|
|
||||||
|
( sm, sc ) =
|
||||||
|
Comp.CalEventInput.init flags newSchedule
|
||||||
|
in
|
||||||
|
( { nm
|
||||||
|
| settings = s
|
||||||
|
, recipients = s.recipients
|
||||||
|
, remindDays = Just s.remindDays
|
||||||
|
, enabled = s.enabled
|
||||||
|
, schedule = Data.Validated.Unknown newSchedule
|
||||||
|
}
|
||||||
|
, Cmd.batch
|
||||||
|
[ nc
|
||||||
|
, Cmd.map CalEventMsg sc
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
SetNotificationSettings (Err err) ->
|
||||||
|
( { model | formError = Just (Util.Http.errorToString err) }, Cmd.none )
|
||||||
|
|
||||||
|
Submit ->
|
||||||
( model, Cmd.none )
|
( model, Cmd.none )
|
||||||
|
|
||||||
|
|
||||||
@ -275,14 +318,22 @@ view extraClasses model =
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
, Html.map CalEventMsg
|
, Html.map CalEventMsg
|
||||||
(Comp.CalEventInput.view "" model.scheduleModel)
|
(Comp.CalEventInput.view ""
|
||||||
|
(Data.Validated.value model.schedule)
|
||||||
|
model.scheduleModel
|
||||||
|
)
|
||||||
, span [ class "small-info" ]
|
, span [ class "small-info" ]
|
||||||
[ text "Specify how often and when this task should run. "
|
[ text "Specify how often and when this task should run. "
|
||||||
, text "Use English 3-letter weekdays. Either a single value, "
|
, text "Use English 3-letter weekdays. Either a single value, "
|
||||||
, text "a list or a '*' (meaning all) is allowed for each part."
|
, text "a list (ex. 1,2,3), a range (ex. 1..3) or a '*' (meaning all) "
|
||||||
|
, text "is allowed for each part."
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
, div [ class "ui divider" ] []
|
, div [ class "ui divider" ] []
|
||||||
|
, div [ class "ui error message" ]
|
||||||
|
[ Maybe.withDefault "" model.formError
|
||||||
|
|> text
|
||||||
|
]
|
||||||
, button
|
, button
|
||||||
[ class "ui primary button"
|
[ class "ui primary button"
|
||||||
, onClick Submit
|
, onClick Submit
|
||||||
|
107
modules/webapp/src/main/elm/Data/CalEvent.elm
Normal file
107
modules/webapp/src/main/elm/Data/CalEvent.elm
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
module Data.CalEvent exposing
|
||||||
|
( CalEvent
|
||||||
|
, everyMonth
|
||||||
|
, fromEvent
|
||||||
|
, makeEvent
|
||||||
|
)
|
||||||
|
|
||||||
|
import Util.Maybe
|
||||||
|
|
||||||
|
|
||||||
|
type alias CalEvent =
|
||||||
|
{ weekday : Maybe String
|
||||||
|
, year : String
|
||||||
|
, month : String
|
||||||
|
, day : String
|
||||||
|
, hour : String
|
||||||
|
, minute : String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
everyMonth : CalEvent
|
||||||
|
everyMonth =
|
||||||
|
CalEvent Nothing "*" "*" "01" "00" "00"
|
||||||
|
|
||||||
|
|
||||||
|
makeEvent : CalEvent -> String
|
||||||
|
makeEvent ev =
|
||||||
|
let
|
||||||
|
datetime =
|
||||||
|
ev.year
|
||||||
|
++ "-"
|
||||||
|
++ ev.month
|
||||||
|
++ "-"
|
||||||
|
++ ev.day
|
||||||
|
++ " "
|
||||||
|
++ ev.hour
|
||||||
|
++ ":"
|
||||||
|
++ ev.minute
|
||||||
|
in
|
||||||
|
case ev.weekday of
|
||||||
|
Just wd ->
|
||||||
|
wd ++ " " ++ datetime
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
datetime
|
||||||
|
|
||||||
|
|
||||||
|
fromEvent : String -> Maybe CalEvent
|
||||||
|
fromEvent str =
|
||||||
|
let
|
||||||
|
init =
|
||||||
|
everyMonth
|
||||||
|
|
||||||
|
parts =
|
||||||
|
String.split " " str
|
||||||
|
in
|
||||||
|
case parts of
|
||||||
|
wd :: date :: time :: [] ->
|
||||||
|
Maybe.andThen
|
||||||
|
(fromDate date)
|
||||||
|
(fromTime time init)
|
||||||
|
|> Maybe.map (withWeekday wd)
|
||||||
|
|
||||||
|
date :: time :: [] ->
|
||||||
|
Maybe.andThen
|
||||||
|
(fromDate date)
|
||||||
|
(fromTime time init)
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
fromDate : String -> CalEvent -> Maybe CalEvent
|
||||||
|
fromDate date ev =
|
||||||
|
let
|
||||||
|
parts =
|
||||||
|
String.split "-" date
|
||||||
|
in
|
||||||
|
case parts of
|
||||||
|
y :: m :: d :: [] ->
|
||||||
|
Just
|
||||||
|
{ ev
|
||||||
|
| year = y
|
||||||
|
, month = m
|
||||||
|
, day = d
|
||||||
|
}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
fromTime : String -> CalEvent -> Maybe CalEvent
|
||||||
|
fromTime time ev =
|
||||||
|
case String.split ":" time of
|
||||||
|
h :: m :: _ :: [] ->
|
||||||
|
Just { ev | hour = h, minute = m }
|
||||||
|
|
||||||
|
h :: m :: [] ->
|
||||||
|
Just { ev | hour = h, minute = m }
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
Nothing
|
||||||
|
|
||||||
|
|
||||||
|
withWeekday : String -> CalEvent -> CalEvent
|
||||||
|
withWeekday wd ev =
|
||||||
|
{ ev | weekday = Util.Maybe.fromString wd }
|
20
modules/webapp/src/main/elm/Data/Validated.elm
Normal file
20
modules/webapp/src/main/elm/Data/Validated.elm
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
module Data.Validated exposing (Validated(..), value)
|
||||||
|
|
||||||
|
|
||||||
|
type Validated a
|
||||||
|
= Valid a
|
||||||
|
| Invalid a
|
||||||
|
| Unknown a
|
||||||
|
|
||||||
|
|
||||||
|
value : Validated a -> a
|
||||||
|
value va =
|
||||||
|
case va of
|
||||||
|
Valid a ->
|
||||||
|
a
|
||||||
|
|
||||||
|
Invalid a ->
|
||||||
|
a
|
||||||
|
|
||||||
|
Unknown a ->
|
||||||
|
a
|
@ -11,6 +11,7 @@
|
|||||||
}
|
}
|
||||||
.calevent-input input.time-input {
|
.calevent-input input.time-input {
|
||||||
border: 0 !important;
|
border: 0 !important;
|
||||||
|
font-family: monospace !important;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.calevent-input .separator {
|
.calevent-input .separator {
|
||||||
@ -27,6 +28,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.default-layout .right-float {
|
.default-layout .right-float {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user