From 2aed7ba1424bfd69709771208f662be92594ab11 Mon Sep 17 00:00:00 2001 From: Eike Kettner Date: Sat, 5 Dec 2020 22:38:27 +0100 Subject: [PATCH] Simplify search bar and search menu The functionality of the search bar is now in the search menu, too. The search menu shows one input field for "textual search", which is either the fulltext search (if enabled) or a basic search in various names. --- .../webapp/src/main/elm/Comp/SearchMenu.elm | 298 ++++++++++++------ .../webapp/src/main/elm/Page/Home/Data.elm | 63 +--- .../webapp/src/main/elm/Page/Home/Update.elm | 38 +-- .../webapp/src/main/elm/Page/Home/View.elm | 26 +- 4 files changed, 233 insertions(+), 192 deletions(-) diff --git a/modules/webapp/src/main/elm/Comp/SearchMenu.elm b/modules/webapp/src/main/elm/Comp/SearchMenu.elm index 8c65c6fb..ab57fcbf 100644 --- a/modules/webapp/src/main/elm/Comp/SearchMenu.elm +++ b/modules/webapp/src/main/elm/Comp/SearchMenu.elm @@ -2,8 +2,12 @@ module Comp.SearchMenu exposing ( Model , Msg(..) , NextState + , TextSearchModel , getItemSearch , init + , isFulltextSearch + , isNamesSearch + , textSearchString , update , updateDrop , view @@ -66,18 +70,21 @@ type alias Model = , untilDueDateModel : DatePicker , untilDueDate : Maybe Int , nameModel : Maybe String - , allNameModel : Maybe String - , fulltextModel : Maybe String + , textSearchModel : TextSearchModel , datePickerInitialized : Bool - , showNameHelp : Bool , customFieldModel : Comp.CustomFieldMultiInput.Model , customValues : CustomFieldValueCollect , sourceModel : Maybe String } -init : Model -init = +type TextSearchModel + = Fulltext (Maybe String) + | Names (Maybe String) + + +init : Flags -> Model +init flags = { tagSelectModel = Comp.TagSelect.init Comp.TagSelect.emptySelection [] , tagSelection = Comp.TagSelect.emptySelection , directionModel = @@ -124,16 +131,87 @@ init = , untilDueDateModel = Comp.DatePicker.emptyModel , untilDueDate = Nothing , nameModel = Nothing - , allNameModel = Nothing - , fulltextModel = Nothing + , textSearchModel = + if flags.config.fullTextSearchEnabled then + Fulltext Nothing + + else + Names Nothing , datePickerInitialized = False - , showNameHelp = False , customFieldModel = Comp.CustomFieldMultiInput.initWith [] , customValues = Data.CustomFieldChange.emptyCollect , sourceModel = Nothing } +updateTextSearch : String -> TextSearchModel -> TextSearchModel +updateTextSearch str model = + let + next = + Util.Maybe.fromString str + in + case model of + Fulltext _ -> + Fulltext next + + Names _ -> + Names next + + +swapTextSearch : TextSearchModel -> TextSearchModel +swapTextSearch model = + case model of + Fulltext s -> + Names s + + Names s -> + Fulltext s + + +textSearchValue : TextSearchModel -> { nameSearch : Maybe String, fullText : Maybe String } +textSearchValue model = + case model of + Fulltext s -> + { nameSearch = Nothing + , fullText = s + } + + Names s -> + { nameSearch = s + , fullText = Nothing + } + + +textSearchString : TextSearchModel -> Maybe String +textSearchString model = + case model of + Fulltext s -> + s + + Names s -> + s + + +isFulltextSearch : Model -> Bool +isFulltextSearch model = + case model.textSearchModel of + Fulltext _ -> + True + + Names _ -> + False + + +isNamesSearch : Model -> Bool +isNamesSearch model = + case model.textSearchModel of + Fulltext _ -> + False + + Names _ -> + True + + getDirection : Model -> Maybe Direction getDirection model = let @@ -164,6 +242,9 @@ getItemSearch model = else "*" ++ s ++ "*" + + textSearch = + textSearchValue model.textSearchModel in { e | tagsInclude = model.tagSelection.includeTags |> List.map .tag |> List.map .id @@ -186,9 +267,9 @@ getItemSearch model = model.nameModel |> Maybe.map amendWildcards , allNames = - model.allNameModel + textSearch.nameSearch |> Maybe.map amendWildcards - , fullText = model.fulltextModel + , fullText = textSearch.fullText , tagCategoriesInclude = model.tagSelection.includeCats |> List.map .name , tagCategoriesExclude = model.tagSelection.excludeCats |> List.map .name , customValues = Data.CustomFieldChange.toFieldValues model.customValues @@ -225,8 +306,13 @@ resetModel model = , fromDueDate = Nothing , untilDueDate = Nothing , nameModel = Nothing - , allNameModel = Nothing - , fulltextModel = Nothing + , textSearchModel = + case model.textSearchModel of + Fulltext _ -> + Fulltext Nothing + + Names _ -> + Names Nothing , customFieldModel = Comp.CustomFieldMultiInput.reset model.customFieldModel @@ -257,11 +343,12 @@ type Msg | GetEquipResp (Result Http.Error EquipmentList) | GetPersonResp (Result Http.Error PersonList) | SetName String - | SetAllName String - | SetFulltext String + | SetTextSearch String + | SwapTextSearch + | SetFulltextSearch + | SetNamesSearch | ResetForm | KeyUpMsg (Maybe KeyCode) - | ToggleNameHelp | FolderSelectMsg Comp.FolderSelect.Msg | GetFolderResp (Result Http.Error FolderList) | SetCorrOrg IdName @@ -641,27 +728,59 @@ updateDrop ddm flags settings msg model = , dragDrop = DD.DragDropData ddm Nothing } - SetAllName str -> - let - next = - Util.Maybe.fromString str - in - { model = { model | allNameModel = next } + SetTextSearch str -> + { model = { model | textSearchModel = updateTextSearch str model.textSearchModel } , cmd = Cmd.none , stateChange = False , dragDrop = DD.DragDropData ddm Nothing } - SetFulltext str -> - let - next = - Util.Maybe.fromString str - in - { model = { model | fulltextModel = next } - , cmd = Cmd.none - , stateChange = False - , dragDrop = DD.DragDropData ddm Nothing - } + SwapTextSearch -> + if flags.config.fullTextSearchEnabled then + { model = { model | textSearchModel = swapTextSearch model.textSearchModel } + , cmd = Cmd.none + , stateChange = False + , dragDrop = DD.DragDropData ddm Nothing + } + + else + { model = model + , cmd = Cmd.none + , stateChange = False + , dragDrop = DD.DragDropData ddm Nothing + } + + SetFulltextSearch -> + case model.textSearchModel of + Fulltext _ -> + { model = model + , cmd = Cmd.none + , stateChange = False + , dragDrop = DD.DragDropData ddm Nothing + } + + Names s -> + { model = { model | textSearchModel = Fulltext s } + , cmd = Cmd.none + , stateChange = False + , dragDrop = DD.DragDropData ddm Nothing + } + + SetNamesSearch -> + case model.textSearchModel of + Fulltext s -> + { model = { model | textSearchModel = Names s } + , cmd = Cmd.none + , stateChange = False + , dragDrop = DD.DragDropData ddm Nothing + } + + Names _ -> + { model = model + , cmd = Cmd.none + , stateChange = False + , dragDrop = DD.DragDropData ddm Nothing + } KeyUpMsg (Just Enter) -> { model = model @@ -677,13 +796,6 @@ updateDrop ddm flags settings msg model = , dragDrop = DD.DragDropData ddm Nothing } - ToggleNameHelp -> - { model = { model | showNameHelp = not model.showNameHelp } - , cmd = Cmd.none - , stateChange = False - , dragDrop = DD.DragDropData ddm Nothing - } - GetFolderResp (Ok fs) -> let model_ = @@ -804,6 +916,54 @@ viewDrop ddd flags settings model = ] ] ] + , div [ class segmentClass ] + [ div + [ class "field" + ] + [ label [] + [ text + (case model.textSearchModel of + Fulltext _ -> + "Fulltext Search" + + Names _ -> + "Search in names" + ) + , a + [ classList + [ ( "right-float", True ) + , ( "invisible hidden", not flags.config.fullTextSearchEnabled ) + ] + , href "#" + , onClick SwapTextSearch + , title "Switch between text search modes" + ] + [ i [ class "small grey exchange alternate icon" ] [] + ] + ] + , input + [ type_ "text" + , onInput SetTextSearch + , Util.Html.onKeyUpCode KeyUpMsg + , textSearchString model.textSearchModel |> Maybe.withDefault "" |> value + , case model.textSearchModel of + Fulltext _ -> + placeholder "Content search…" + + Names _ -> + placeholder "Search in various names…" + ] + [] + , span [ class "small-info" ] + [ case model.textSearchModel of + Fulltext _ -> + text "Fulltext search in document contents and notes." + + Names _ -> + text "Looks in correspondents, concerned entities, item name and notes." + ] + ] + ] , div [ classList [ ( segmentClass, True ) @@ -883,68 +1043,6 @@ viewDrop ddd flags settings model = model.customFieldModel ) ] - , div [ class segmentClass ] - [ formHeader (Icons.searchIcon "") "Text Search" - , div - [ classList - [ ( "field", True ) - , ( "invisible hidden", not flags.config.fullTextSearchEnabled ) - ] - ] - [ label [] [ text "Fulltext Search" ] - , input - [ type_ "text" - , onInput SetFulltext - , Util.Html.onKeyUpCode KeyUpMsg - , model.fulltextModel |> Maybe.withDefault "" |> value - , placeholder "Fulltext search in results…" - ] - [] - , span [ class "small-info" ] - [ text "Fulltext search in document contents and notes." - ] - ] - , div [ class "field" ] - [ label [] - [ text "Names" - , a - [ class "right-float" - , href "#" - , onClick ToggleNameHelp - ] - [ i [ class "small grey help link icon" ] [] - ] - ] - , input - [ type_ "text" - , onInput SetAllName - , Util.Html.onKeyUpCode KeyUpMsg - , model.allNameModel |> Maybe.withDefault "" |> value - , placeholder "Search in various names…" - ] - [] - , span - [ classList - [ ( "small-info", True ) - ] - ] - [ text "Looks in correspondents, concerned entities, item name and notes." - ] - , p - [ classList - [ ( "small-info", True ) - , ( "invisible hidden", not model.showNameHelp ) - ] - ] - [ text "Use wildcards " - , code [] [ text "*" ] - , text " at beginning or end. They are added automatically on both sides " - , text "if not present in the search term and the term is not quoted. Press " - , em [] [ text "Enter" ] - , text " to start searching." - ] - ] - ] , div [ classList [ ( segmentClass, True ) diff --git a/modules/webapp/src/main/elm/Page/Home/Data.elm b/modules/webapp/src/main/elm/Page/Home/Data.elm index 7837b5b8..6c328b6d 100644 --- a/modules/webapp/src/main/elm/Page/Home/Data.elm +++ b/modules/webapp/src/main/elm/Page/Home/Data.elm @@ -6,7 +6,6 @@ module Page.Home.Data exposing , SelectActionMode(..) , SelectViewModel , ViewMode(..) - , defaultSearchType , doSearchCmd , init , initSelectViewModel @@ -20,7 +19,6 @@ module Page.Home.Data exposing 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 @@ -52,7 +50,6 @@ type alias Model = , searchTypeDropdown : Comp.FixedDropdown.Model SearchType , searchTypeDropdownValue : SearchType , lastSearchType : SearchType - , contentOnlySearch : Maybe String , dragDropData : DD.DragDropData , scrollToCard : Maybe String } @@ -88,6 +85,9 @@ type ViewMode init : Flags -> ViewMode -> Model init flags viewMode = let + searchMenuModel = + Comp.SearchMenu.init flags + searchTypeOptions = if flags.config.fullTextSearchEnabled then [ BasicSearch, ContentOnlySearch ] @@ -95,7 +95,7 @@ init flags viewMode = else [ BasicSearch ] in - { searchMenuModel = Comp.SearchMenu.init + { searchMenuModel = searchMenuModel , itemListModel = Comp.ItemCardList.init , searchInProgress = False , searchOffset = 0 @@ -105,9 +105,13 @@ init flags viewMode = , searchTypeDropdown = Comp.FixedDropdown.initMap searchTypeString searchTypeOptions - , searchTypeDropdownValue = defaultSearchType flags + , searchTypeDropdownValue = + if Comp.SearchMenu.isFulltextSearch searchMenuModel then + ContentOnlySearch + + else + BasicSearch , lastSearchType = BasicSearch - , contentOnlySearch = Nothing , dragDropData = DD.DragDropData DD.init Nothing , scrollToCard = Nothing @@ -115,15 +119,6 @@ init flags viewMode = } -defaultSearchType : Flags -> SearchType -defaultSearchType flags = - if flags.config.fullTextSearchEnabled then - ContentOnlySearch - - else - BasicSearch - - menuCollapsed : Model -> Bool menuCollapsed model = case model.viewMode of @@ -165,7 +160,6 @@ type Msg | SetBasicSearch String | SearchTypeMsg (Comp.FixedDropdown.Msg SearchType) | KeyUpSearchbarMsg (Maybe KeyCode) - | SetContentOnly String | ScrollResult (Result Dom.Error ()) | ClearItemDetailId | SelectAllItems @@ -227,12 +221,7 @@ itemNav id model = doSearchCmd : SearchParam -> Model -> Cmd Msg doSearchCmd param model = - case param.searchType of - BasicSearch -> - doSearchDefaultCmd param model - - ContentOnlySearch -> - doSearchIndexCmd param model + doSearchDefaultCmd param model doSearchDefaultCmd : SearchParam -> Model -> Cmd Msg @@ -254,36 +243,6 @@ doSearchDefaultCmd param model = Api.itemSearch param.flags mask ItemSearchAddResp -doSearchIndexCmd : SearchParam -> Model -> Cmd Msg -doSearchIndexCmd param model = - case model.contentOnlySearch of - Just q -> - let - mask = - { query = q - , limit = param.pageSize - , offset = param.offset - } - in - if param.offset == 0 then - Api.itemIndexSearch param.flags mask (ItemSearchResp param.scroll) - - else - Api.itemIndexSearch param.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 = param.pageSize } - in - Api.itemSearch param.flags mask (ItemSearchResp param.scroll) - - resultsBelowLimit : UiSettings -> Model -> Bool resultsBelowLimit settings model = let diff --git a/modules/webapp/src/main/elm/Page/Home/Update.elm b/modules/webapp/src/main/elm/Page/Home/Update.elm index a2f5dc6d..6b01115f 100644 --- a/modules/webapp/src/main/elm/Page/Home/Update.elm +++ b/modules/webapp/src/main/elm/Page/Home/Update.elm @@ -52,10 +52,7 @@ update mId key flags settings msg model = ResetSearch -> let nm = - { model - | searchOffset = 0 - , contentOnlySearch = Nothing - } + { model | searchOffset = 0 } in update mId key flags settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm @@ -76,6 +73,12 @@ update mId key flags settings msg model = { model | searchMenuModel = nextState.model , dragDropData = nextState.dragDrop + , searchTypeDropdownValue = + if Comp.SearchMenu.isFulltextSearch nextState.model then + ContentOnlySearch + + else + BasicSearch } ( m2, c2, s2 ) = @@ -261,21 +264,10 @@ update mId key flags settings msg model = SetBasicSearch str -> let smMsg = - case model.searchTypeDropdownValue of - BasicSearch -> - SearchMenuMsg (Comp.SearchMenu.SetAllName str) - - ContentOnlySearch -> - SetContentOnly str + SearchMenuMsg (Comp.SearchMenu.SetTextSearch 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 ) = @@ -293,23 +285,17 @@ update mId key flags settings msg model = next = case mvChange of Just BasicSearch -> - Just - ( { m0 | contentOnlySearch = Nothing } - , Maybe.withDefault "" model.contentOnlySearch - ) + Just Comp.SearchMenu.SetNamesSearch Just ContentOnlySearch -> - Just - ( { m0 | contentOnlySearch = model.searchMenuModel.allNameModel } - , "" - ) + Just Comp.SearchMenu.SetFulltextSearch _ -> Nothing in case next of - Just ( m_, nstr ) -> - update mId key flags settings (SearchMenuMsg (Comp.SearchMenu.SetAllName nstr)) m_ + Just lm_ -> + update mId key flags settings (SearchMenuMsg lm_) m0 Nothing -> withSub ( m0, Cmd.none ) diff --git a/modules/webapp/src/main/elm/Page/Home/View.elm b/modules/webapp/src/main/elm/Page/Home/View.elm index f2adfe63..b59fcb8e 100644 --- a/modules/webapp/src/main/elm/Page/Home/View.elm +++ b/modules/webapp/src/main/elm/Page/Home/View.elm @@ -285,12 +285,8 @@ viewSearchBar flags model = (searchTypeString model.searchTypeDropdownValue) searchInput = - case model.searchTypeDropdownValue of - BasicSearch -> - model.searchMenuModel.allNameModel - - ContentOnlySearch -> - model.contentOnlySearch + Comp.SearchMenu.textSearchString + model.searchMenuModel.textSearchModel searchTypeClass = if flags.config.fullTextSearchEnabled then @@ -328,7 +324,7 @@ viewSearchBar flags model = , href "#" , onClick (DoSearch model.searchTypeDropdownValue) ] - (if hasMoreSearch model && model.searchTypeDropdownValue == BasicSearch then + (if hasMoreSearch model then [ i [ class "icons search-corner-icons" ] [ i [ class "tiny blue circle icon" ] [] ] @@ -339,7 +335,14 @@ viewSearchBar flags model = ) , input [ type_ "text" - , placeholder "Quick Search …" + , placeholder + (case model.searchTypeDropdownValue of + ContentOnlySearch -> + "Content search…" + + BasicSearch -> + "Search in names…" + ) , onInput SetBasicSearch , Util.Html.onKeyUpCode KeyUpSearchbarMsg , Maybe.map value searchInput @@ -381,12 +384,7 @@ hasMoreSearch model = Comp.SearchMenu.getItemSearch model.searchMenuModel is_ = - case model.lastSearchType of - BasicSearch -> - { is | allNames = Nothing } - - ContentOnlySearch -> - Api.Model.ItemSearch.empty + { is | allNames = Nothing, fullText = Nothing } in is_ /= Api.Model.ItemSearch.empty