2020-10-25 23:08:40 +01:00

282 lines
6.8 KiB
Elm

module Page.Home.Data exposing
( Model
, Msg(..)
, SearchType(..)
, SelectActionMode(..)
, SelectViewModel
, ViewMode(..)
, defaultSearchType
, doSearchCmd
, init
, initSelectViewModel
, itemNav
, menuCollapsed
, resultsBelowLimit
, searchTypeString
, selectActive
)
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.ItemLightList exposing (ItemLightList)
import Api.Model.ItemSearch
import Browser.Dom as Dom
import Comp.FixedDropdown
import Comp.ItemCardList
import Comp.ItemDetail.EditMenu
import Comp.SearchMenu
import Comp.YesNoDimmer
import Data.Flags exposing (Flags)
import Data.ItemNav exposing (ItemNav)
import Data.Items
import Data.UiSettings exposing (UiSettings)
import Http
import Set exposing (Set)
import Throttle exposing (Throttle)
import Util.Html exposing (KeyCode(..))
import Util.ItemDragDrop as DD
type alias Model =
{ searchMenuModel : Comp.SearchMenu.Model
, itemListModel : Comp.ItemCardList.Model
, searchInProgress : Bool
, viewMode : ViewMode
, searchOffset : Int
, moreAvailable : Bool
, moreInProgress : Bool
, throttle : Throttle Msg
, searchTypeDropdown : Comp.FixedDropdown.Model SearchType
, searchType : SearchType
, searchTypeForm : SearchType
, contentOnlySearch : Maybe String
, dragDropData : DD.DragDropData
, scrollToCard : Maybe String
}
type alias SelectViewModel =
{ ids : Set String
, action : SelectActionMode
, deleteAllConfirm : Comp.YesNoDimmer.Model
, editModel : Comp.ItemDetail.EditMenu.Model
}
initSelectViewModel : SelectViewModel
initSelectViewModel =
{ ids = Set.empty
, action = NoneAction
, deleteAllConfirm = Comp.YesNoDimmer.initActive
, editModel = Comp.ItemDetail.EditMenu.init
}
type ViewMode
= SimpleView
| SearchView
| SelectView SelectViewModel
init : Flags -> Model
init flags =
let
searchTypeOptions =
if flags.config.fullTextSearchEnabled then
[ BasicSearch, ContentOnlySearch ]
else
[ BasicSearch ]
in
{ searchMenuModel = Comp.SearchMenu.init
, itemListModel = Comp.ItemCardList.init
, searchInProgress = False
, searchOffset = 0
, moreAvailable = True
, moreInProgress = False
, throttle = Throttle.create 1
, searchTypeDropdown =
Comp.FixedDropdown.initMap searchTypeString
searchTypeOptions
, searchType = BasicSearch
, searchTypeForm = defaultSearchType flags
, contentOnlySearch = Nothing
, dragDropData =
DD.DragDropData DD.init Nothing
, scrollToCard = Nothing
, viewMode = SimpleView
}
defaultSearchType : Flags -> SearchType
defaultSearchType flags =
if flags.config.fullTextSearchEnabled then
ContentOnlySearch
else
BasicSearch
menuCollapsed : Model -> Bool
menuCollapsed model =
case model.viewMode of
SimpleView ->
True
SearchView ->
False
SelectView _ ->
False
selectActive : Model -> Bool
selectActive model =
case model.viewMode of
SimpleView ->
False
SearchView ->
False
SelectView _ ->
True
type Msg
= Init
| SearchMenuMsg Comp.SearchMenu.Msg
| ResetSearch
| ItemCardListMsg Comp.ItemCardList.Msg
| ItemSearchResp Bool (Result Http.Error ItemLightList)
| ItemSearchAddResp (Result Http.Error ItemLightList)
| DoSearch
| ToggleSearchMenu
| ToggleSelectView
| LoadMore
| UpdateThrottle
| SetBasicSearch String
| SearchTypeMsg (Comp.FixedDropdown.Msg SearchType)
| KeyUpMsg (Maybe KeyCode)
| SetContentOnly String
| ScrollResult (Result Dom.Error ())
| ClearItemDetailId
| SelectAllItems
| SelectNoItems
| RequestDeleteSelected
| DeleteSelectedConfirmMsg Comp.YesNoDimmer.Msg
| EditSelectedItems
| EditMenuMsg Comp.ItemDetail.EditMenu.Msg
| MultiUpdateResp (Result Http.Error BasicResult)
| ReplaceChangedItemsResp (Result Http.Error ItemLightList)
type SearchType
= BasicSearch
| ContentSearch
| ContentOnlySearch
type SelectActionMode
= NoneAction
| DeleteSelected
| EditSelected
searchTypeString : SearchType -> String
searchTypeString st =
case st of
BasicSearch ->
"Names"
ContentSearch ->
"Contents"
ContentOnlySearch ->
"Contents Only"
itemNav : String -> Model -> ItemNav
itemNav id model =
let
prev =
Comp.ItemCardList.prevItem model.itemListModel id
next =
Comp.ItemCardList.nextItem model.itemListModel id
in
{ prev = Maybe.map .id prev
, next = Maybe.map .id next
}
doSearchCmd : Flags -> UiSettings -> Int -> Bool -> Model -> Cmd Msg
doSearchCmd flags settings offset scroll model =
case model.searchType of
BasicSearch ->
doSearchDefaultCmd flags settings offset scroll model
ContentSearch ->
doSearchDefaultCmd flags settings offset scroll model
ContentOnlySearch ->
doSearchIndexCmd flags settings offset scroll model
doSearchDefaultCmd : Flags -> UiSettings -> Int -> Bool -> Model -> Cmd Msg
doSearchDefaultCmd flags settings offset scroll model =
let
smask =
Comp.SearchMenu.getItemSearch model.searchMenuModel
mask =
{ smask
| limit = settings.itemSearchPageSize
, offset = offset
}
in
if offset == 0 then
Api.itemSearch flags mask (ItemSearchResp scroll)
else
Api.itemSearch flags mask ItemSearchAddResp
doSearchIndexCmd : Flags -> UiSettings -> Int -> Bool -> Model -> Cmd Msg
doSearchIndexCmd flags settings offset scroll model =
case model.contentOnlySearch of
Just q ->
let
mask =
{ query = q
, limit = settings.itemSearchPageSize
, offset = offset
}
in
if offset == 0 then
Api.itemIndexSearch flags mask (ItemSearchResp scroll)
else
Api.itemIndexSearch flags mask ItemSearchAddResp
Nothing ->
-- If there is no fulltext query, render simply the most
-- current ones
let
emptyMask =
Api.Model.ItemSearch.empty
mask =
{ emptyMask | limit = settings.itemSearchPageSize }
in
Api.itemSearch flags mask (ItemSearchResp scroll)
resultsBelowLimit : UiSettings -> Model -> Bool
resultsBelowLimit settings model =
let
len =
Data.Items.length model.itemListModel.results
in
len < settings.itemSearchPageSize