Start with send-mail widget

This commit is contained in:
Eike Kettner 2020-01-08 01:26:39 +01:00
parent 4490a444a9
commit 51ce48997c
6 changed files with 317 additions and 5 deletions

View File

@ -1325,11 +1325,18 @@ components:
schemas:
SimpleMail:
description: |
A simple e-mail.
A simple e-mail related to an item.
The mail may contain the item attachments as mail attachments.
If all item attachments should be send, set
`addAllAttachments` to `true`. Otherwise set it to `false` and
specify a list of file-ids that you want to include.
required:
- recipients
- subject
- body
- addAllAttachments
- attachmentIds
properties:
recipients:
type: array
@ -1339,6 +1346,13 @@ components:
type: string
body:
type: string
addAllAttachments:
type: boolean
attachemntIds:
type: array
items:
type: string
format: ident
EmailSettingsList:
description: |
A list of user email settings.

View File

@ -395,7 +395,9 @@ viewSingle model =
]
renderDefault =
[ List.head model.selected |> Maybe.map renderClosed |> Maybe.withDefault (renderPlaceholder model)
[ List.head model.selected
|> Maybe.map renderClosed
|> Maybe.withDefault (renderPlaceholder model)
, renderMenu model
]

View File

@ -76,7 +76,10 @@ init ems =
{ makeOption = \s -> { value = Data.SSLType.toString s, text = Data.SSLType.label s }
, placeholder = ""
, options = Data.SSLType.all
, selected = Data.SSLType.fromString ems.sslType
, selected =
Data.SSLType.fromString ems.sslType
|> Maybe.withDefault Data.SSLType.None
|> Just
}
, ignoreCertificates = ems.ignoreCertificates
}

View File

@ -22,6 +22,7 @@ import Api.Model.TagList exposing (TagList)
import Browser.Navigation as Nav
import Comp.DatePicker
import Comp.Dropdown exposing (isDropdownChangeMsg)
import Comp.ItemMail
import Comp.YesNoDimmer
import Data.Direction exposing (Direction)
import Data.Flags exposing (Flags)
@ -57,6 +58,8 @@ type alias Model =
, itemProposals : ItemProposals
, dueDate : Maybe Int
, dueDatePicker : DatePicker
, itemMail : Comp.ItemMail.Model
, mailOpen : Bool
}
@ -116,6 +119,8 @@ emptyModel =
, itemProposals = Api.Model.ItemProposals.empty
, dueDate = Nothing
, dueDatePicker = Comp.DatePicker.emptyModel
, itemMail = Comp.ItemMail.emptyModel
, mailOpen = False
}
@ -158,6 +163,8 @@ type Msg
| GetProposalResp (Result Http.Error ItemProposals)
| RemoveDueDate
| RemoveDate
| ItemMailMsg Comp.ItemMail.Msg
| ToggleMail
@ -282,12 +289,16 @@ update key flags next msg model =
let
( dp, dpc ) =
Comp.DatePicker.init
( im, ic ) =
Comp.ItemMail.init flags
in
( { model | itemDatePicker = dp, dueDatePicker = dp }
( { model | itemDatePicker = dp, dueDatePicker = dp, itemMail = im }
, Cmd.batch
[ getOptions flags
, Cmd.map ItemDatePickerMsg dpc
, Cmd.map DueDatePickerMsg dpc
, Cmd.map ItemMailMsg ic
]
)
@ -690,6 +701,29 @@ update key flags next msg model =
GetProposalResp (Err _) ->
( model, Cmd.none )
ItemMailMsg m ->
let
( im, fa ) =
Comp.ItemMail.update m model.itemMail
in
case fa of
Comp.ItemMail.FormNone ->
( { model | itemMail = im }, Cmd.none )
Comp.ItemMail.FormCancel ->
( { model
| itemMail = Comp.ItemMail.clear im
, mailOpen = False
}
, Cmd.none
)
Comp.ItemMail.FormSend sm ->
Debug.todo "implement send"
ToggleMail ->
( { model | mailOpen = not model.mailOpen }, Cmd.none )
-- view
@ -711,6 +745,7 @@ view inav model =
, div
[ classList
[ ( "ui ablue-comp menu", True )
, ( "top attached", model.mailOpen )
]
]
[ a [ class "item", Page.href HomePage ]
@ -743,13 +778,25 @@ view inav model =
[ ( "toggle item", True )
, ( "active", model.menuOpen )
]
, title "Expand Menu"
, title "Edit item"
, onClick ToggleMenu
, href ""
]
[ i [ class "edit icon" ] []
]
, a
[ classList
[ ( "toggle item", True )
, ( "active", model.mailOpen )
]
, title "Send Mail"
, onClick ToggleMail
, href "#"
]
[ i [ class "mail icon" ] []
]
]
, renderMailForm model
, div [ class "ui grid" ]
[ Html.map YesNoMsg (Comp.YesNoDimmer.view model.deleteConfirm)
, div
@ -1197,3 +1244,18 @@ renderDueDateSuggestions model =
Util.Time.formatDate
(List.take 5 model.itemProposals.dueDate)
SetDueDateSuggestion
renderMailForm : Model -> Html Msg
renderMailForm model =
div
[ classList
[ ( "ui bottom attached segment", True )
, ( "invisible hidden", not model.mailOpen )
]
]
[ h4 [ class "ui header" ]
[ text "Send this item via E-Mail"
]
, Html.map ItemMailMsg (Comp.ItemMail.view model.itemMail)
]

View File

@ -0,0 +1,225 @@
module Comp.ItemMail exposing
( FormAction(..)
, Model
, Msg
, clear
, emptyModel
, init
, update
, view
)
import Api
import Api.Model.EmailSettingsList exposing (EmailSettingsList)
import Api.Model.SimpleMail exposing (SimpleMail)
import Comp.Dropdown
import Data.Flags exposing (Flags)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onCheck, onClick, onInput)
import Http
import Util.Http
type alias Model =
{ connectionModel : Comp.Dropdown.Model String
, subject : String
, receiver : String
, body : String
, attachAll : Bool
, formError : Maybe String
}
type Msg
= SetSubject String
| SetReceiver String
| SetBody String
| ConnMsg (Comp.Dropdown.Msg String)
| ConnResp (Result Http.Error EmailSettingsList)
| ToggleAttachAll
| Cancel
| Send
type FormAction
= FormSend SimpleMail
| FormCancel
| FormNone
emptyModel : Model
emptyModel =
{ connectionModel =
Comp.Dropdown.makeSingle
{ makeOption = \a -> { value = a, text = a }
, placeholder = "Select connection..."
}
, subject = ""
, receiver = ""
, body = ""
, attachAll = True
, formError = Nothing
}
init : Flags -> ( Model, Cmd Msg )
init flags =
( emptyModel, Api.getMailSettings flags "" ConnResp )
clear : Model -> Model
clear model =
{ model
| subject = ""
, receiver = ""
, body = ""
}
update : Msg -> Model -> ( Model, FormAction )
update msg model =
case msg of
SetSubject str ->
( { model | subject = str }, FormNone )
SetReceiver str ->
( { model | receiver = str }, FormNone )
SetBody str ->
( { model | body = str }, FormNone )
ConnMsg m ->
let
( cm, _ ) =
--TODO dropdown doesn't use cmd!!
Comp.Dropdown.update m model.connectionModel
in
( { model | connectionModel = cm }, FormNone )
ToggleAttachAll ->
( { model | attachAll = not model.attachAll }, FormNone )
ConnResp (Ok list) ->
let
names =
List.map .name list.items
cm =
Comp.Dropdown.makeSingleList
{ makeOption = \a -> { value = a, text = a }
, placeholder = "Select Connection..."
, options = names
, selected = List.head names
}
in
( { model
| connectionModel = cm
, formError =
if names == [] then
Just "No E-Mail connections configured. Goto user settings to add one."
else
Nothing
}
, FormNone
)
ConnResp (Err err) ->
( { model | formError = Just (Util.Http.errorToString err) }, FormNone )
Cancel ->
( model, FormCancel )
Send ->
let
rec =
String.split "," model.receiver
sm =
SimpleMail rec model.subject model.body model.attachAll []
in
( model, FormSend sm )
isValid : Model -> Bool
isValid model =
model.receiver
/= ""
&& model.subject
/= ""
&& model.body
/= ""
&& model.formError
== Nothing
view : Model -> Html Msg
view model =
div
[ classList
[ ( "ui form", True )
, ( "error", model.formError /= Nothing )
]
]
[ div [ class "field" ]
[ label [] [ text "Send via" ]
, Html.map ConnMsg (Comp.Dropdown.view model.connectionModel)
]
, div [ class "ui error message" ]
[ Maybe.withDefault "" model.formError |> text
]
, div [ class "field" ]
[ label []
[ text "Receiver(s)"
, span [ class "muted" ]
[ text "Separate multiple recipients by comma" ]
]
, input
[ type_ "text"
, onInput SetReceiver
, value model.receiver
]
[]
]
, div [ class "field" ]
[ label [] [ text "Subject" ]
, input
[ type_ "text"
, onInput SetSubject
, value model.subject
]
[]
]
, div [ class "field" ]
[ label [] [ text "Body" ]
, textarea [ onInput SetBody ]
[ text model.body ]
]
, div [ class "inline field" ]
[ div [ class "ui checkbox" ]
[ input
[ type_ "checkbox"
, checked model.attachAll
, onCheck (\_ -> ToggleAttachAll)
]
[]
, label [] [ text "Include all item attachments" ]
]
]
, button
[ classList
[ ( "ui primary button", True )
, ( "disabled", not (isValid model) )
]
, onClick Send
]
[ text "Send"
]
, button
[ class "ui secondary button"
, onClick Cancel
]
[ text "Cancel"
]
]

View File

@ -65,6 +65,12 @@
padding-right: 1em;
}
label span.muted {
font-size: smaller;
color: rgba(0,0,0,0.6);
margin-left: 0.5em;
}
.ui.search.dropdown.open {
z-index: 20;
}