mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-02-15 20:33:26 +00:00
Start with send-mail widget
This commit is contained in:
parent
4490a444a9
commit
51ce48997c
@ -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.
|
||||
|
@ -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
|
||||
]
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
]
|
||||
|
225
modules/webapp/src/main/elm/Comp/ItemMail.elm
Normal file
225
modules/webapp/src/main/elm/Comp/ItemMail.elm
Normal 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"
|
||||
]
|
||||
]
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user