mirror of
				https://github.com/TheAnachronism/docspell.git
				synced 2025-10-31 17:50:11 +00:00 
			
		
		
		
	Start with send-mail widget
This commit is contained in:
		| @@ -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; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user