Eike Kettner 795cd8bc80 Set search when clicking on parts of the item card
When user clicks on correspondent etc. on an item card, the search is
set to this value.
2020-11-14 01:45:10 +01:00

690 lines
20 KiB
Elm

module Page.Home.Update exposing (update)
import Api
import Api.Model.IdList exposing (IdList)
import Api.Model.ItemLightList exposing (ItemLightList)
import Api.Model.ItemSearch
import Browser.Navigation as Nav
import Comp.FixedDropdown
import Comp.ItemCard
import Comp.ItemCardList
import Comp.ItemDetail.EditMenu exposing (SaveNameState(..))
import Comp.ItemDetail.FormChange exposing (FormChange(..))
import Comp.SearchMenu
import Comp.YesNoDimmer
import Data.Flags exposing (Flags)
import Data.ItemSelection
import Data.Items
import Data.UiSettings exposing (UiSettings)
import Page exposing (Page(..))
import Page.Home.Data exposing (..)
import Process
import Scroll
import Set exposing (Set)
import Task
import Throttle
import Time
import Util.Html exposing (KeyCode(..))
import Util.ItemDragDrop as DD
import Util.Maybe
import Util.String
import Util.Update
update : Maybe String -> Nav.Key -> Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
update mId key flags settings msg model =
case msg of
Init ->
Util.Update.andThen2
[ update mId key flags settings (SearchMenuMsg Comp.SearchMenu.Init)
, doSearch flags settings True
]
model
ResetSearch ->
let
nm =
{ model
| searchOffset = 0
, searchType = defaultSearchType flags
}
in
update mId key flags settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm
SearchMenuMsg m ->
let
nextState =
Comp.SearchMenu.updateDrop
model.dragDropData.model
flags
settings
m
model.searchMenuModel
dropCmd =
DD.makeUpdateCmd flags (\_ -> DoSearch) nextState.dragDrop.dropped
newModel =
{ model
| searchMenuModel = nextState.model
, dragDropData = nextState.dragDrop
}
( m2, c2, s2 ) =
if nextState.stateChange && not model.searchInProgress then
doSearch flags settings False newModel
else
withSub ( newModel, Cmd.none )
in
( m2
, Cmd.batch
[ c2
, Cmd.map SearchMenuMsg nextState.cmd
, dropCmd
]
, s2
)
ItemCardListMsg m ->
let
result =
Comp.ItemCardList.updateDrag model.dragDropData.model
flags
m
model.itemListModel
searchMsg =
case result.linkTarget of
Comp.ItemCard.LinkNone ->
Cmd.none
Comp.ItemCard.LinkCorrOrg id ->
Util.Update.cmdUnit (SearchMenuMsg (Comp.SearchMenu.SetCorrOrg id))
Comp.ItemCard.LinkCorrPerson id ->
Util.Update.cmdUnit (SearchMenuMsg (Comp.SearchMenu.SetCorrPerson id))
Comp.ItemCard.LinkConcPerson id ->
Util.Update.cmdUnit (SearchMenuMsg (Comp.SearchMenu.SetConcPerson id))
Comp.ItemCard.LinkConcEquip id ->
Util.Update.cmdUnit (SearchMenuMsg (Comp.SearchMenu.SetConcEquip id))
Comp.ItemCard.LinkFolder id ->
Util.Update.cmdUnit (SearchMenuMsg (Comp.SearchMenu.SetFolder id))
nextView =
case ( model.viewMode, result.selection ) of
( SelectView svm, Data.ItemSelection.Active ids ) ->
SelectView { svm | ids = ids }
( v, _ ) ->
v
in
withSub
( { model
| itemListModel = result.model
, viewMode = nextView
, dragDropData = DD.DragDropData result.dragModel Nothing
}
, Cmd.batch [ Cmd.map ItemCardListMsg result.cmd, searchMsg ]
)
ItemSearchResp scroll (Ok list) ->
let
noff =
settings.itemSearchPageSize
m =
{ model
| searchInProgress = False
, searchOffset = noff
, moreAvailable = list.groups /= []
}
in
Util.Update.andThen2
[ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.SetResults list))
, if scroll then
scrollToCard mId
else
\next -> ( next, Cmd.none, Sub.none )
]
m
ItemSearchAddResp (Ok list) ->
let
noff =
model.searchOffset + settings.itemSearchPageSize
m =
{ model
| searchInProgress = False
, moreInProgress = False
, searchOffset = noff
, moreAvailable = list.groups /= []
}
in
Util.Update.andThen2
[ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.AddResults list))
]
m
ItemSearchAddResp (Err _) ->
withSub
( { model
| moreInProgress = False
}
, Cmd.none
)
ItemSearchResp _ (Err _) ->
withSub
( { model
| searchInProgress = False
}
, Cmd.none
)
DoSearch ->
let
nm =
{ model | searchOffset = 0 }
in
if model.searchInProgress then
withSub ( model, Cmd.none )
else
doSearch flags settings False nm
ToggleSearchMenu ->
let
nextView =
case model.viewMode of
SimpleView ->
SearchView
SearchView ->
SimpleView
SelectView _ ->
SimpleView
in
withSub
( { model | viewMode = nextView }
, Cmd.none
)
ToggleSelectView ->
let
( nextView, cmd ) =
case model.viewMode of
SimpleView ->
( SelectView initSelectViewModel, loadEditModel flags )
SearchView ->
( SelectView initSelectViewModel, loadEditModel flags )
SelectView _ ->
( SearchView, Cmd.none )
in
withSub
( { model
| viewMode = nextView
}
, cmd
)
LoadMore ->
if model.moreAvailable then
doSearchMore flags settings model |> withSub
else
withSub ( model, Cmd.none )
UpdateThrottle ->
let
( newThrottle, cmd ) =
Throttle.update model.throttle
in
withSub ( { model | throttle = newThrottle }, cmd )
SetBasicSearch str ->
let
smMsg =
case model.searchTypeForm of
BasicSearch ->
SearchMenuMsg (Comp.SearchMenu.SetAllName str)
ContentSearch ->
SearchMenuMsg (Comp.SearchMenu.SetFulltext str)
ContentOnlySearch ->
SetContentOnly str
in
update mId key flags settings smMsg model
SetContentOnly str ->
withSub
( { model | contentOnlySearch = Util.Maybe.fromString str }
, Cmd.none
)
SearchTypeMsg lm ->
let
( sm, mv ) =
Comp.FixedDropdown.update lm model.searchTypeDropdown
mvChange =
Util.Maybe.filter (\a -> a /= model.searchTypeForm) mv
m0 =
{ model
| searchTypeDropdown = sm
, searchTypeForm = Maybe.withDefault model.searchTypeForm mv
}
next =
case mvChange of
Just BasicSearch ->
Just
( { m0 | contentOnlySearch = Nothing }
, Maybe.withDefault "" model.contentOnlySearch
)
Just ContentOnlySearch ->
Just
( { m0 | contentOnlySearch = model.searchMenuModel.allNameModel }
, ""
)
_ ->
Nothing
in
case next of
Just ( m_, nstr ) ->
update mId key flags settings (SearchMenuMsg (Comp.SearchMenu.SetAllName nstr)) m_
Nothing ->
withSub ( m0, Cmd.none )
KeyUpMsg (Just Enter) ->
update mId key flags settings DoSearch model
KeyUpMsg _ ->
withSub ( model, Cmd.none )
ScrollResult _ ->
let
cmd =
Process.sleep 800 |> Task.perform (always ClearItemDetailId)
in
withSub ( model, cmd )
ClearItemDetailId ->
noSub ( { model | scrollToCard = Nothing }, Cmd.none )
SelectAllItems ->
case model.viewMode of
SelectView svm ->
let
visible =
Data.Items.idSet model.itemListModel.results
svm_ =
{ svm | ids = Set.union svm.ids visible }
in
noSub
( { model | viewMode = SelectView svm_ }
, Cmd.none
)
_ ->
noSub ( model, Cmd.none )
SelectNoItems ->
case model.viewMode of
SelectView svm ->
let
svm_ =
{ svm | ids = Set.empty }
in
noSub
( { model | viewMode = SelectView svm_ }
, Cmd.none
)
_ ->
noSub ( model, Cmd.none )
DeleteSelectedConfirmMsg lmsg ->
case model.viewMode of
SelectView svm ->
let
( confirmModel, confirmed ) =
Comp.YesNoDimmer.update lmsg svm.deleteAllConfirm
cmd =
if confirmed then
Api.deleteAllItems flags svm.ids DeleteAllResp
else
Cmd.none
act =
if confirmModel.active || confirmed then
DeleteSelected
else
NoneAction
in
noSub
( { model
| viewMode =
SelectView
{ svm
| deleteAllConfirm = confirmModel
, action = act
}
}
, cmd
)
_ ->
noSub ( model, Cmd.none )
DeleteAllResp (Ok res) ->
if res.success then
let
nm =
{ model | viewMode = SearchView }
in
doSearch flags settings False nm
else
noSub ( model, Cmd.none )
DeleteAllResp (Err _) ->
noSub ( model, Cmd.none )
RequestDeleteSelected ->
case model.viewMode of
SelectView svm ->
if svm.ids == Set.empty then
noSub ( model, Cmd.none )
else
let
lmsg =
DeleteSelectedConfirmMsg Comp.YesNoDimmer.activate
model_ =
{ model | viewMode = SelectView { svm | action = DeleteSelected } }
in
update mId key flags settings lmsg model_
_ ->
noSub ( model, Cmd.none )
EditSelectedItems ->
case model.viewMode of
SelectView svm ->
if svm.action == EditSelected then
noSub
( { model | viewMode = SelectView { svm | action = NoneAction } }
, Cmd.none
)
else if svm.ids == Set.empty then
noSub ( model, Cmd.none )
else
noSub
( { model | viewMode = SelectView { svm | action = EditSelected } }
, Cmd.none
)
_ ->
noSub ( model, Cmd.none )
EditMenuMsg lmsg ->
case model.viewMode of
SelectView svm ->
let
res =
Comp.ItemDetail.EditMenu.update flags lmsg svm.editModel
svm_ =
{ svm
| editModel = res.model
, saveNameState =
case res.change of
NameChange _ ->
Saving
_ ->
svm.saveNameState
}
cmd_ =
Cmd.map EditMenuMsg res.cmd
sub_ =
Sub.map EditMenuMsg res.sub
upCmd =
Comp.ItemDetail.FormChange.multiUpdate flags
svm.ids
res.change
(MultiUpdateResp res.change)
in
( { model | viewMode = SelectView svm_ }
, Cmd.batch [ cmd_, upCmd ]
, sub_
)
_ ->
noSub ( model, Cmd.none )
MultiUpdateResp change (Ok res) ->
let
nm =
updateSelectViewNameState res.success model change
in
if res.success then
case model.viewMode of
SelectView svm ->
-- replace changed items in the view
noSub ( nm, loadChangedItems flags svm.ids )
_ ->
noSub ( nm, Cmd.none )
else
noSub ( nm, Cmd.none )
MultiUpdateResp change (Err _) ->
( updateSelectViewNameState False model change
, Cmd.none
, Sub.none
)
ReplaceChangedItemsResp (Ok items) ->
noSub ( replaceItems model items, Cmd.none )
ReplaceChangedItemsResp (Err _) ->
noSub ( model, Cmd.none )
UiSettingsUpdated ->
let
defaultViewMode =
if settings.searchMenuVisible then
SearchView
else
SimpleView
viewMode =
case model.viewMode of
SimpleView ->
defaultViewMode
SearchView ->
defaultViewMode
sv ->
sv
model_ =
{ model | viewMode = viewMode }
in
update mId key flags settings DoSearch model_
--- Helpers
updateSelectViewNameState : Bool -> Model -> FormChange -> Model
updateSelectViewNameState success model change =
case model.viewMode of
SelectView svm ->
case change of
NameChange _ ->
let
svm_ =
{ svm
| saveNameState =
if success then
SaveSuccess
else
SaveFailed
}
in
{ model | viewMode = SelectView svm_ }
_ ->
model
_ ->
model
replaceItems : Model -> ItemLightList -> Model
replaceItems model newItems =
let
listModel =
model.itemListModel
changed =
Data.Items.replaceIn listModel.results newItems
newList =
{ listModel | results = changed }
in
{ model | itemListModel = newList }
loadChangedItems : Flags -> Set String -> Cmd Msg
loadChangedItems flags ids =
if Set.isEmpty ids then
Cmd.none
else
let
searchInit =
Api.Model.ItemSearch.empty
idList =
IdList (Set.toList ids)
search =
{ searchInit
| itemSubset = Just idList
, limit = Set.size ids
}
in
Api.itemSearch flags search ReplaceChangedItemsResp
scrollToCard : Maybe String -> Model -> ( Model, Cmd Msg, Sub Msg )
scrollToCard mId model =
let
scroll id =
Scroll.scroll id 0.5 0.5 0.5 0.5
in
case mId of
Just id ->
( { model | scrollToCard = mId }
, Task.attempt ScrollResult (scroll id)
, Sub.none
)
Nothing ->
( model, Cmd.none, Sub.none )
loadEditModel : Flags -> Cmd Msg
loadEditModel flags =
Cmd.map EditMenuMsg (Comp.ItemDetail.EditMenu.loadModel flags)
doSearch : Flags -> UiSettings -> Bool -> Model -> ( Model, Cmd Msg, Sub Msg )
doSearch flags settings scroll model =
let
stype =
if
not (menuCollapsed model)
|| Util.String.isNothingOrBlank model.contentOnlySearch
then
BasicSearch
else
model.searchTypeForm
model_ =
{ model | searchType = stype }
searchCmd =
doSearchCmd flags settings 0 scroll model_
( newThrottle, cmd ) =
Throttle.try searchCmd model.throttle
in
withSub
( { model_
| searchInProgress = cmd /= Cmd.none
, searchOffset = 0
, throttle = newThrottle
}
, cmd
)
doSearchMore : Flags -> UiSettings -> Model -> ( Model, Cmd Msg )
doSearchMore flags settings model =
let
cmd =
doSearchCmd flags settings model.searchOffset False model
in
( { model | moreInProgress = True }
, cmd
)
withSub : ( Model, Cmd Msg ) -> ( Model, Cmd Msg, Sub Msg )
withSub ( m, c ) =
( m
, c
, Throttle.ifNeeded
(Time.every 500 (\_ -> UpdateThrottle))
m.throttle
)
noSub : ( Model, Cmd Msg ) -> ( Model, Cmd Msg, Sub Msg )
noSub ( m, c ) =
( m, c, Sub.none )