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: |   schemas: | ||||||
|     SimpleMail: |     SimpleMail: | ||||||
|       description: | |       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: |       required: | ||||||
|         - recipients |         - recipients | ||||||
|         - subject |         - subject | ||||||
|         - body |         - body | ||||||
|  |         - addAllAttachments | ||||||
|  |         - attachmentIds | ||||||
|       properties: |       properties: | ||||||
|         recipients: |         recipients: | ||||||
|           type: array |           type: array | ||||||
| @@ -1339,6 +1346,13 @@ components: | |||||||
|           type: string |           type: string | ||||||
|         body: |         body: | ||||||
|           type: string |           type: string | ||||||
|  |         addAllAttachments: | ||||||
|  |           type: boolean | ||||||
|  |         attachemntIds: | ||||||
|  |           type: array | ||||||
|  |           items: | ||||||
|  |             type: string | ||||||
|  |             format: ident | ||||||
|     EmailSettingsList: |     EmailSettingsList: | ||||||
|       description: | |       description: | | ||||||
|         A list of user email settings. |         A list of user email settings. | ||||||
|   | |||||||
| @@ -395,7 +395,9 @@ viewSingle model = | |||||||
|                 ] |                 ] | ||||||
|  |  | ||||||
|         renderDefault = |         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 |             , renderMenu model | ||||||
|             ] |             ] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -76,7 +76,10 @@ init ems = | |||||||
|             { makeOption = \s -> { value = Data.SSLType.toString s, text = Data.SSLType.label s } |             { makeOption = \s -> { value = Data.SSLType.toString s, text = Data.SSLType.label s } | ||||||
|             , placeholder = "" |             , placeholder = "" | ||||||
|             , options = Data.SSLType.all |             , 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 |     , ignoreCertificates = ems.ignoreCertificates | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ import Api.Model.TagList exposing (TagList) | |||||||
| import Browser.Navigation as Nav | import Browser.Navigation as Nav | ||||||
| import Comp.DatePicker | import Comp.DatePicker | ||||||
| import Comp.Dropdown exposing (isDropdownChangeMsg) | import Comp.Dropdown exposing (isDropdownChangeMsg) | ||||||
|  | import Comp.ItemMail | ||||||
| import Comp.YesNoDimmer | import Comp.YesNoDimmer | ||||||
| import Data.Direction exposing (Direction) | import Data.Direction exposing (Direction) | ||||||
| import Data.Flags exposing (Flags) | import Data.Flags exposing (Flags) | ||||||
| @@ -57,6 +58,8 @@ type alias Model = | |||||||
|     , itemProposals : ItemProposals |     , itemProposals : ItemProposals | ||||||
|     , dueDate : Maybe Int |     , dueDate : Maybe Int | ||||||
|     , dueDatePicker : DatePicker |     , dueDatePicker : DatePicker | ||||||
|  |     , itemMail : Comp.ItemMail.Model | ||||||
|  |     , mailOpen : Bool | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -116,6 +119,8 @@ emptyModel = | |||||||
|     , itemProposals = Api.Model.ItemProposals.empty |     , itemProposals = Api.Model.ItemProposals.empty | ||||||
|     , dueDate = Nothing |     , dueDate = Nothing | ||||||
|     , dueDatePicker = Comp.DatePicker.emptyModel |     , dueDatePicker = Comp.DatePicker.emptyModel | ||||||
|  |     , itemMail = Comp.ItemMail.emptyModel | ||||||
|  |     , mailOpen = False | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -158,6 +163,8 @@ type Msg | |||||||
|     | GetProposalResp (Result Http.Error ItemProposals) |     | GetProposalResp (Result Http.Error ItemProposals) | ||||||
|     | RemoveDueDate |     | RemoveDueDate | ||||||
|     | RemoveDate |     | RemoveDate | ||||||
|  |     | ItemMailMsg Comp.ItemMail.Msg | ||||||
|  |     | ToggleMail | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -282,12 +289,16 @@ update key flags next msg model = | |||||||
|             let |             let | ||||||
|                 ( dp, dpc ) = |                 ( dp, dpc ) = | ||||||
|                     Comp.DatePicker.init |                     Comp.DatePicker.init | ||||||
|  |  | ||||||
|  |                 ( im, ic ) = | ||||||
|  |                     Comp.ItemMail.init flags | ||||||
|             in |             in | ||||||
|             ( { model | itemDatePicker = dp, dueDatePicker = dp } |             ( { model | itemDatePicker = dp, dueDatePicker = dp, itemMail = im } | ||||||
|             , Cmd.batch |             , Cmd.batch | ||||||
|                 [ getOptions flags |                 [ getOptions flags | ||||||
|                 , Cmd.map ItemDatePickerMsg dpc |                 , Cmd.map ItemDatePickerMsg dpc | ||||||
|                 , Cmd.map DueDatePickerMsg dpc |                 , Cmd.map DueDatePickerMsg dpc | ||||||
|  |                 , Cmd.map ItemMailMsg ic | ||||||
|                 ] |                 ] | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
| @@ -690,6 +701,29 @@ update key flags next msg model = | |||||||
|         GetProposalResp (Err _) -> |         GetProposalResp (Err _) -> | ||||||
|             ( model, Cmd.none ) |             ( 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 | -- view | ||||||
| @@ -711,6 +745,7 @@ view inav model = | |||||||
|         , div |         , div | ||||||
|             [ classList |             [ classList | ||||||
|                 [ ( "ui ablue-comp menu", True ) |                 [ ( "ui ablue-comp menu", True ) | ||||||
|  |                 , ( "top attached", model.mailOpen ) | ||||||
|                 ] |                 ] | ||||||
|             ] |             ] | ||||||
|             [ a [ class "item", Page.href HomePage ] |             [ a [ class "item", Page.href HomePage ] | ||||||
| @@ -743,13 +778,25 @@ view inav model = | |||||||
|                     [ ( "toggle item", True ) |                     [ ( "toggle item", True ) | ||||||
|                     , ( "active", model.menuOpen ) |                     , ( "active", model.menuOpen ) | ||||||
|                     ] |                     ] | ||||||
|                 , title "Expand Menu" |                 , title "Edit item" | ||||||
|                 , onClick ToggleMenu |                 , onClick ToggleMenu | ||||||
|                 , href "" |                 , href "" | ||||||
|                 ] |                 ] | ||||||
|                 [ i [ class "edit icon" ] [] |                 [ 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" ] |         , div [ class "ui grid" ] | ||||||
|             [ Html.map YesNoMsg (Comp.YesNoDimmer.view model.deleteConfirm) |             [ Html.map YesNoMsg (Comp.YesNoDimmer.view model.deleteConfirm) | ||||||
|             , div |             , div | ||||||
| @@ -1197,3 +1244,18 @@ renderDueDateSuggestions model = | |||||||
|         Util.Time.formatDate |         Util.Time.formatDate | ||||||
|         (List.take 5 model.itemProposals.dueDate) |         (List.take 5 model.itemProposals.dueDate) | ||||||
|         SetDueDateSuggestion |         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; |     padding-right: 1em; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | label span.muted { | ||||||
|  |     font-size: smaller; | ||||||
|  |     color: rgba(0,0,0,0.6); | ||||||
|  |     margin-left: 0.5em; | ||||||
|  | } | ||||||
|  |  | ||||||
| .ui.search.dropdown.open { | .ui.search.dropdown.open { | ||||||
|     z-index: 20; |     z-index: 20; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user