Save name in item detail while typing

This commit is contained in:
Eike Kettner 2020-09-21 17:35:11 +02:00
parent 6b58bba1c8
commit 42a7a003a7
6 changed files with 193 additions and 106 deletions

View File

@ -6,8 +6,8 @@ module Comp.ItemDetail exposing
) )
import Browser.Navigation as Nav import Browser.Navigation as Nav
import Comp.ItemDetail.Model import Comp.ItemDetail.Model exposing (Msg(..))
import Comp.ItemDetail.Update exposing (Msg) import Comp.ItemDetail.Update
import Comp.ItemDetail.View exposing (..) import Comp.ItemDetail.View exposing (..)
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (UiSettings)

View File

@ -1,17 +1,24 @@
module Comp.ItemDetail.Model exposing module Comp.ItemDetail.Model exposing
( AttachmentRename ( AttachmentRename
, Model , Model
, Msg(..)
, NotesField(..) , NotesField(..)
, SaveNameState(..)
, emptyModel , emptyModel
, isEditNotes , isEditNotes
) )
import Api.Model.BasicResult exposing (BasicResult) import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.EquipmentList exposing (EquipmentList)
import Api.Model.FolderItem exposing (FolderItem) import Api.Model.FolderItem exposing (FolderItem)
import Api.Model.FolderList exposing (FolderList)
import Api.Model.IdName exposing (IdName) import Api.Model.IdName exposing (IdName)
import Api.Model.ItemDetail exposing (ItemDetail) import Api.Model.ItemDetail exposing (ItemDetail)
import Api.Model.ItemProposals exposing (ItemProposals) import Api.Model.ItemProposals exposing (ItemProposals)
import Api.Model.ReferenceList exposing (ReferenceList)
import Api.Model.SentMails exposing (SentMails)
import Api.Model.Tag exposing (Tag) import Api.Model.Tag exposing (Tag)
import Api.Model.TagList exposing (TagList)
import Comp.AttachmentMeta import Comp.AttachmentMeta
import Comp.DatePicker import Comp.DatePicker
import Comp.DetailEdit import Comp.DetailEdit
@ -22,14 +29,17 @@ import Comp.MarkdownInput
import Comp.SentMails import Comp.SentMails
import Comp.YesNoDimmer import Comp.YesNoDimmer
import Data.Direction exposing (Direction) import Data.Direction exposing (Direction)
import Data.Fields exposing (Field)
import DatePicker exposing (DatePicker) import DatePicker exposing (DatePicker)
import Dict exposing (Dict) import Dict exposing (Dict)
import File exposing (File) import File exposing (File)
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html5.DragDrop as DD import Html5.DragDrop as DD
import Http
import Page exposing (Page(..)) import Page exposing (Page(..))
import Set exposing (Set) import Set exposing (Set)
import Throttle exposing (Throttle)
import Util.Tag import Util.Tag
@ -46,6 +56,8 @@ type alias Model =
, folderModel : Comp.Dropdown.Model IdName , folderModel : Comp.Dropdown.Model IdName
, allFolders : List FolderItem , allFolders : List FolderItem
, nameModel : String , nameModel : String
, nameState : SaveNameState
, nameSaveThrottle : Throttle Msg
, notesModel : Maybe String , notesModel : Maybe String
, notesField : NotesField , notesField : NotesField
, deleteItemConfirm : Comp.YesNoDimmer.Model , deleteItemConfirm : Comp.YesNoDimmer.Model
@ -143,6 +155,8 @@ emptyModel =
} }
, allFolders = [] , allFolders = []
, nameModel = "" , nameModel = ""
, nameState = SaveSuccess
, nameSaveThrottle = Throttle.create 1
, notesModel = Nothing , notesModel = Nothing
, notesField = ViewNotes , notesField = ViewNotes
, deleteItemConfirm = Comp.YesNoDimmer.emptyModel , deleteItemConfirm = Comp.YesNoDimmer.emptyModel
@ -171,3 +185,89 @@ emptyModel =
, modalEdit = Nothing , modalEdit = Nothing
, attachRename = Nothing , attachRename = Nothing
} }
type Msg
= ToggleMenu
| ReloadItem
| Init
| SetItem ItemDetail
| SetActiveAttachment Int
| TagDropdownMsg (Comp.Dropdown.Msg Tag)
| DirDropdownMsg (Comp.Dropdown.Msg Direction)
| OrgDropdownMsg (Comp.Dropdown.Msg IdName)
| CorrPersonMsg (Comp.Dropdown.Msg IdName)
| ConcPersonMsg (Comp.Dropdown.Msg IdName)
| ConcEquipMsg (Comp.Dropdown.Msg IdName)
| GetTagsResp (Result Http.Error TagList)
| GetOrgResp (Result Http.Error ReferenceList)
| GetPersonResp (Result Http.Error ReferenceList)
| GetEquipResp (Result Http.Error EquipmentList)
| SetName String
| SetNotes String
| ToggleEditNotes
| NotesEditMsg Comp.MarkdownInput.Msg
| SaveNotes
| ConfirmItem
| UnconfirmItem
| SetCorrOrgSuggestion IdName
| SetCorrPersonSuggestion IdName
| SetConcPersonSuggestion IdName
| SetConcEquipSuggestion IdName
| SetItemDateSuggestion Int
| SetDueDateSuggestion Int
| ItemDatePickerMsg Comp.DatePicker.Msg
| DueDatePickerMsg Comp.DatePicker.Msg
| DeleteItemConfirm Comp.YesNoDimmer.Msg
| RequestDelete
| SaveResp (Result Http.Error BasicResult)
| DeleteResp (Result Http.Error BasicResult)
| GetItemResp (Result Http.Error ItemDetail)
| GetProposalResp (Result Http.Error ItemProposals)
| RemoveDueDate
| RemoveDate
| ItemMailMsg Comp.ItemMail.Msg
| ToggleMail
| SendMailResp (Result Http.Error BasicResult)
| SentMailsMsg Comp.SentMails.Msg
| ToggleSentMails
| SentMailsResp (Result Http.Error SentMails)
| AttachMetaClick String
| AttachMetaMsg String Comp.AttachmentMeta.Msg
| TogglePdfNativeView Bool
| RequestDeleteAttachment String
| DeleteAttachConfirm String Comp.YesNoDimmer.Msg
| DeleteAttachResp (Result Http.Error BasicResult)
| AddFilesToggle
| AddFilesMsg Comp.Dropzone.Msg
| AddFilesSubmitUpload
| AddFilesUploadResp String (Result Http.Error BasicResult)
| AddFilesProgress String Http.Progress
| AddFilesReset
| AttachDDMsg (DD.Msg String String)
| ModalEditMsg Comp.DetailEdit.Msg
| StartTagModal
| StartCorrOrgModal
| StartCorrPersonModal
| StartConcPersonModal
| StartEquipModal
| CloseModal
| EditAttachNameStart String
| EditAttachNameCancel
| EditAttachNameSet String
| EditAttachNameSubmit
| EditAttachNameResp (Result Http.Error BasicResult)
| GetFolderResp (Result Http.Error FolderList)
| FolderDropdownMsg (Comp.Dropdown.Msg IdName)
| StartEditCorrOrgModal
| StartEditPersonModal (Comp.Dropdown.Model IdName)
| StartEditEquipModal
| ResetHiddenMsg Field (Result Http.Error BasicResult)
| SaveNameResp (Result Http.Error BasicResult)
| UpdateThrottle
type SaveNameState
= Saving
| SaveSuccess
| SaveFailed

View File

@ -1,21 +1,16 @@
module Comp.ItemDetail.Update exposing (Msg(..), update) module Comp.ItemDetail.Update exposing (update)
import Api import Api
import Api.Model.BasicResult exposing (BasicResult) import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.DirectionValue exposing (DirectionValue) import Api.Model.DirectionValue exposing (DirectionValue)
import Api.Model.EquipmentList exposing (EquipmentList)
import Api.Model.FolderList exposing (FolderList)
import Api.Model.IdName exposing (IdName) import Api.Model.IdName exposing (IdName)
import Api.Model.ItemDetail exposing (ItemDetail) import Api.Model.ItemDetail exposing (ItemDetail)
import Api.Model.ItemProposals exposing (ItemProposals)
import Api.Model.MoveAttachment exposing (MoveAttachment) import Api.Model.MoveAttachment exposing (MoveAttachment)
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)
import Api.Model.ReferenceList exposing (ReferenceList) import Api.Model.ReferenceList exposing (ReferenceList)
import Api.Model.SentMails exposing (SentMails)
import Api.Model.Tag exposing (Tag) import Api.Model.Tag exposing (Tag)
import Api.Model.TagList exposing (TagList)
import Browser.Navigation as Nav import Browser.Navigation as Nav
import Comp.AttachmentMeta import Comp.AttachmentMeta
import Comp.DatePicker import Comp.DatePicker
@ -23,7 +18,15 @@ import Comp.DetailEdit
import Comp.Dropdown exposing (isDropdownChangeMsg) import Comp.Dropdown exposing (isDropdownChangeMsg)
import Comp.Dropzone import Comp.Dropzone
import Comp.EquipmentForm import Comp.EquipmentForm
import Comp.ItemDetail.Model exposing (AttachmentRename, Model, NotesField(..), isEditNotes) import Comp.ItemDetail.Model
exposing
( AttachmentRename
, Model
, Msg(..)
, NotesField(..)
, SaveNameState(..)
, isEditNotes
)
import Comp.ItemMail import Comp.ItemMail
import Comp.MarkdownInput import Comp.MarkdownInput
import Comp.OrgForm import Comp.OrgForm
@ -43,6 +46,8 @@ import Http
import Page exposing (Page(..)) import Page exposing (Page(..))
import Ports import Ports
import Set exposing (Set) import Set exposing (Set)
import Throttle
import Time
import Util.File exposing (makeFileId) import Util.File exposing (makeFileId)
import Util.Folder exposing (mkFolderOption) import Util.Folder exposing (mkFolderOption)
import Util.Http import Util.Http
@ -51,85 +56,6 @@ import Util.Maybe
import Util.String import Util.String
type Msg
= ToggleMenu
| ReloadItem
| Init
| SetItem ItemDetail
| SetActiveAttachment Int
| TagDropdownMsg (Comp.Dropdown.Msg Tag)
| DirDropdownMsg (Comp.Dropdown.Msg Direction)
| OrgDropdownMsg (Comp.Dropdown.Msg IdName)
| CorrPersonMsg (Comp.Dropdown.Msg IdName)
| ConcPersonMsg (Comp.Dropdown.Msg IdName)
| ConcEquipMsg (Comp.Dropdown.Msg IdName)
| GetTagsResp (Result Http.Error TagList)
| GetOrgResp (Result Http.Error ReferenceList)
| GetPersonResp (Result Http.Error ReferenceList)
| GetEquipResp (Result Http.Error EquipmentList)
| SetName String
| SaveName
| SetNotes String
| ToggleEditNotes
| NotesEditMsg Comp.MarkdownInput.Msg
| SaveNotes
| ConfirmItem
| UnconfirmItem
| SetCorrOrgSuggestion IdName
| SetCorrPersonSuggestion IdName
| SetConcPersonSuggestion IdName
| SetConcEquipSuggestion IdName
| SetItemDateSuggestion Int
| SetDueDateSuggestion Int
| ItemDatePickerMsg Comp.DatePicker.Msg
| DueDatePickerMsg Comp.DatePicker.Msg
| DeleteItemConfirm Comp.YesNoDimmer.Msg
| RequestDelete
| SaveResp (Result Http.Error BasicResult)
| DeleteResp (Result Http.Error BasicResult)
| GetItemResp (Result Http.Error ItemDetail)
| GetProposalResp (Result Http.Error ItemProposals)
| RemoveDueDate
| RemoveDate
| ItemMailMsg Comp.ItemMail.Msg
| ToggleMail
| SendMailResp (Result Http.Error BasicResult)
| SentMailsMsg Comp.SentMails.Msg
| ToggleSentMails
| SentMailsResp (Result Http.Error SentMails)
| AttachMetaClick String
| AttachMetaMsg String Comp.AttachmentMeta.Msg
| TogglePdfNativeView Bool
| RequestDeleteAttachment String
| DeleteAttachConfirm String Comp.YesNoDimmer.Msg
| DeleteAttachResp (Result Http.Error BasicResult)
| AddFilesToggle
| AddFilesMsg Comp.Dropzone.Msg
| AddFilesSubmitUpload
| AddFilesUploadResp String (Result Http.Error BasicResult)
| AddFilesProgress String Http.Progress
| AddFilesReset
| AttachDDMsg (DD.Msg String String)
| ModalEditMsg Comp.DetailEdit.Msg
| StartTagModal
| StartCorrOrgModal
| StartCorrPersonModal
| StartConcPersonModal
| StartEquipModal
| CloseModal
| EditAttachNameStart String
| EditAttachNameCancel
| EditAttachNameSet String
| EditAttachNameSubmit
| EditAttachNameResp (Result Http.Error BasicResult)
| GetFolderResp (Result Http.Error FolderList)
| FolderDropdownMsg (Comp.Dropdown.Msg IdName)
| StartEditCorrOrgModal
| StartEditPersonModal (Comp.Dropdown.Model IdName)
| StartEditEquipModal
| ResetHiddenMsg Field (Result Http.Error BasicResult)
update : Nav.Key -> Flags -> Maybe String -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) update : Nav.Key -> Flags -> Maybe String -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
update key flags next settings msg model = update key flags next settings msg model =
case msg of case msg of
@ -265,6 +191,7 @@ update key flags next settings msg model =
( { m8 ( { m8
| item = item | item = item
, nameModel = item.name , nameModel = item.name
, nameState = SaveSuccess
, notesModel = item.notes , notesModel = item.notes
, notesField = , notesField =
if Util.String.isNothingOrBlank item.notes then if Util.String.isNothingOrBlank item.notes then
@ -448,10 +375,28 @@ update key flags next settings msg model =
noSub ( newModel, Cmd.batch [ save, Cmd.map ConcEquipMsg c2 ] ) noSub ( newModel, Cmd.batch [ save, Cmd.map ConcEquipMsg c2 ] )
SetName str -> SetName str ->
noSub ( { model | nameModel = str }, Cmd.none ) case Util.Maybe.fromString str of
Just newName ->
let
nm =
{ model | nameModel = newName }
SaveName -> cmd_ =
noSub ( model, setName flags model ) setName flags nm
( newThrottle, cmd ) =
Throttle.try cmd_ nm.nameSaveThrottle
in
withSub
( { nm
| nameState = Saving
, nameSaveThrottle = newThrottle
}
, cmd
)
Nothing ->
noSub ( { model | nameModel = str, nameState = SaveFailed }, Cmd.none )
SetNotes str -> SetNotes str ->
noSub noSub
@ -659,6 +604,25 @@ update key flags next settings msg model =
SaveResp (Err _) -> SaveResp (Err _) ->
noSub ( model, Cmd.none ) noSub ( model, Cmd.none )
SaveNameResp (Ok res) ->
if res.success then
noSub
( { model
| nameState = SaveSuccess
, item = setItemName model.item model.nameModel
}
, Cmd.none
)
else
noSub
( { model | nameState = SaveFailed }
, Cmd.none
)
SaveNameResp (Err _) ->
noSub ( { model | nameState = SaveFailed }, Cmd.none )
DeleteResp (Ok res) -> DeleteResp (Ok res) ->
if res.success then if res.success then
case next of case next of
@ -1257,6 +1221,13 @@ update key flags next settings msg model =
ResetHiddenMsg _ _ -> ResetHiddenMsg _ _ ->
noSub ( model, Cmd.none ) noSub ( model, Cmd.none )
UpdateThrottle ->
let
( newThrottle, cmd ) =
Throttle.update model.nameSaveThrottle
in
withSub ( { model | nameSaveThrottle = newThrottle }, cmd )
--- Helper --- Helper
@ -1359,7 +1330,7 @@ setName flags model =
Cmd.none Cmd.none
else else
Api.setItemName flags model.item.id text SaveResp Api.setItemName flags model.item.id text SaveNameResp
setNotes : Flags -> Model -> Cmd Msg setNotes : Flags -> Model -> Cmd Msg
@ -1396,6 +1367,16 @@ noSub ( m, c ) =
( m, c, Sub.none ) ( m, c, Sub.none )
withSub : ( Model, Cmd Msg ) -> ( Model, Cmd Msg, Sub Msg )
withSub ( m, c ) =
( m
, c
, Throttle.ifNeeded
(Time.every 400 (\_ -> UpdateThrottle))
m.nameSaveThrottle
)
resetField : Flags -> String -> (Field -> Result Http.Error BasicResult -> msg) -> Field -> Cmd msg resetField : Flags -> String -> (Field -> Result Http.Error BasicResult -> msg) -> Field -> Cmd msg
resetField flags item tagger field = resetField flags item tagger field =
case field of case field of
@ -1436,3 +1417,8 @@ resetHiddenFields :
resetHiddenFields settings flags item tagger = resetHiddenFields settings flags item tagger =
List.filter (Data.UiSettings.fieldHidden settings) Data.Fields.all List.filter (Data.UiSettings.fieldHidden settings) Data.Fields.all
|> List.map (resetField flags item tagger) |> List.map (resetField flags item tagger)
setItemName : ItemDetail -> String -> ItemDetail
setItemName item name =
{ item | name = name }

View File

@ -6,14 +6,13 @@ import Comp.DatePicker
import Comp.DetailEdit import Comp.DetailEdit
import Comp.Dropdown import Comp.Dropdown
import Comp.Dropzone import Comp.Dropzone
import Comp.ItemDetail.Model exposing (Model, NotesField(..)) import Comp.ItemDetail.Model exposing (Model, Msg(..), NotesField(..), SaveNameState(..))
import Comp.ItemDetail.Update exposing (Msg(..))
import Comp.ItemMail import Comp.ItemMail
import Comp.MarkdownInput import Comp.MarkdownInput
import Comp.SentMails import Comp.SentMails
import Comp.YesNoDimmer import Comp.YesNoDimmer
import Data.Direction import Data.Direction
import Data.Fields exposing (Field) import Data.Fields
import Data.Icons as Icons import Data.Icons as Icons
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (UiSettings)
import DatePicker import DatePicker
@ -801,14 +800,16 @@ renderEditForm settings model =
] ]
, div [ class " field" ] , div [ class " field" ]
[ label [] [ text "Name" ] [ label [] [ text "Name" ]
, div [ class "ui action input" ] , div [ class "ui icon input" ]
[ input [ type_ "text", value model.nameModel, onInput SetName ] [] [ input [ type_ "text", value model.nameModel, onInput SetName ] []
, button , i
[ class "ui icon button" [ classList
, onClick SaveName [ ( "green check icon", model.nameState == SaveSuccess )
] , ( "red exclamation triangle icon", model.nameState == SaveFailed )
[ i [ class "save outline icon" ] [] , ( "sync loading icon", model.nameState == Saving )
]
] ]
[]
] ]
] ]
, optional [ Data.Fields.Folder ] <| , optional [ Data.Fields.Folder ] <|

View File

@ -3,7 +3,7 @@ module Page.ItemDetail.Data exposing (Model, Msg(..), emptyModel)
import Api.Model.ItemDetail exposing (ItemDetail) import Api.Model.ItemDetail exposing (ItemDetail)
import Browser.Dom as Dom import Browser.Dom as Dom
import Comp.ItemDetail import Comp.ItemDetail
import Comp.ItemDetail.Update import Comp.ItemDetail.Model
import Http import Http
@ -20,6 +20,6 @@ emptyModel =
type Msg type Msg
= Init String = Init String
| ItemDetailMsg Comp.ItemDetail.Update.Msg | ItemDetailMsg Comp.ItemDetail.Model.Msg
| ItemResp (Result Http.Error ItemDetail) | ItemResp (Result Http.Error ItemDetail)
| ScrollResult (Result Dom.Error ()) | ScrollResult (Result Dom.Error ())

View File

@ -3,7 +3,7 @@ module Page.ItemDetail.Update exposing (update)
import Api import Api
import Browser.Navigation as Nav import Browser.Navigation as Nav
import Comp.ItemDetail import Comp.ItemDetail
import Comp.ItemDetail.Update import Comp.ItemDetail.Model
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (UiSettings)
import Page.ItemDetail.Data exposing (Model, Msg(..)) import Page.ItemDetail.Data exposing (Model, Msg(..))
@ -21,7 +21,7 @@ update key flags next settings msg model =
flags flags
next next
settings settings
Comp.ItemDetail.Update.Init Comp.ItemDetail.Model.Init
model.detail model.detail
task = task =
@ -49,7 +49,7 @@ update key flags next settings msg model =
ItemResp (Ok item) -> ItemResp (Ok item) ->
let let
lmsg = lmsg =
Comp.ItemDetail.Update.SetItem item Comp.ItemDetail.Model.SetItem item
in in
update key flags next settings (ItemDetailMsg lmsg) model update key flags next settings (ItemDetailMsg lmsg) model