mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-23 10:58:26 +00:00
Select bookmarks in search menu
This commit is contained in:
202
modules/webapp/src/main/elm/Comp/BookmarkChooser.elm
Normal file
202
modules/webapp/src/main/elm/Comp/BookmarkChooser.elm
Normal file
@ -0,0 +1,202 @@
|
||||
module Comp.BookmarkChooser exposing
|
||||
( Model
|
||||
, Msg
|
||||
, Selection
|
||||
, emptySelection
|
||||
, getQueries
|
||||
, init
|
||||
, isEmpty
|
||||
, isEmptySelection
|
||||
, update
|
||||
, view
|
||||
)
|
||||
|
||||
import Api.Model.ShareDetail exposing (ShareDetail)
|
||||
import Data.BookmarkedQuery exposing (AllBookmarks, BookmarkedQuery)
|
||||
import Data.Icons as Icons
|
||||
import Html exposing (Html, a, div, i, span, text)
|
||||
import Html.Attributes exposing (class, classList, href)
|
||||
import Html.Events exposing (onClick)
|
||||
import Messages.Comp.BookmarkChooser exposing (Texts)
|
||||
import Set exposing (Set)
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ all : AllBookmarks
|
||||
}
|
||||
|
||||
|
||||
init : AllBookmarks -> Model
|
||||
init all =
|
||||
{ all = all
|
||||
}
|
||||
|
||||
|
||||
isEmpty : Model -> Bool
|
||||
isEmpty model =
|
||||
model.all == Data.BookmarkedQuery.allBookmarksEmpty
|
||||
|
||||
|
||||
type alias Selection =
|
||||
{ user : Set String
|
||||
, collective : Set String
|
||||
, shares : Set String
|
||||
}
|
||||
|
||||
|
||||
emptySelection : Selection
|
||||
emptySelection =
|
||||
{ user = Set.empty, collective = Set.empty, shares = Set.empty }
|
||||
|
||||
|
||||
isEmptySelection : Selection -> Bool
|
||||
isEmptySelection sel =
|
||||
sel == emptySelection
|
||||
|
||||
|
||||
type Kind
|
||||
= User
|
||||
| Collective
|
||||
| Share
|
||||
|
||||
|
||||
type Msg
|
||||
= Toggle Kind String
|
||||
|
||||
|
||||
getQueries : Model -> Selection -> List BookmarkedQuery
|
||||
getQueries model sel =
|
||||
let
|
||||
member set bm =
|
||||
Set.member bm.name set
|
||||
|
||||
filterBookmarks f bms =
|
||||
Data.BookmarkedQuery.filter f bms |> Data.BookmarkedQuery.map identity
|
||||
in
|
||||
List.concat
|
||||
[ filterBookmarks (member sel.user) model.all.user
|
||||
, filterBookmarks (member sel.collective) model.all.collective
|
||||
, List.map shareToBookmark model.all.shares
|
||||
|> List.filter (member sel.shares)
|
||||
]
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
update : Msg -> Model -> Selection -> ( Model, Selection )
|
||||
update msg model current =
|
||||
let
|
||||
toggle name set =
|
||||
if Set.member name set then
|
||||
Set.remove name set
|
||||
|
||||
else
|
||||
Set.insert name set
|
||||
in
|
||||
case msg of
|
||||
Toggle kind name ->
|
||||
case kind of
|
||||
User ->
|
||||
( model, { current | user = toggle name current.user } )
|
||||
|
||||
Collective ->
|
||||
( model, { current | collective = toggle name current.collective } )
|
||||
|
||||
Share ->
|
||||
( model, { current | shares = toggle name current.shares } )
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> Model -> Selection -> Html Msg
|
||||
view texts model selection =
|
||||
div [ class "flex flex-col" ]
|
||||
[ userBookmarks texts model selection
|
||||
, collBookmarks texts model selection
|
||||
, shares texts model selection
|
||||
]
|
||||
|
||||
|
||||
userBookmarks : Texts -> Model -> Selection -> Html Msg
|
||||
userBookmarks texts model sel =
|
||||
div
|
||||
[ class "mb-2"
|
||||
, classList [ ( "hidden", Data.BookmarkedQuery.emptyBookmarks == model.all.user ) ]
|
||||
]
|
||||
[ div [ class " text-sm font-semibold py-0.5 " ]
|
||||
[ text texts.userLabel
|
||||
]
|
||||
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
||||
(Data.BookmarkedQuery.map (mkItem "fa fa-bookmark" sel User) model.all.user)
|
||||
]
|
||||
|
||||
|
||||
collBookmarks : Texts -> Model -> Selection -> Html Msg
|
||||
collBookmarks texts model sel =
|
||||
div
|
||||
[ class "mb-2"
|
||||
, classList [ ( "hidden", Data.BookmarkedQuery.emptyBookmarks == model.all.collective ) ]
|
||||
]
|
||||
[ div [ class " text-sm font-semibold py-0.5 " ]
|
||||
[ text texts.collectiveLabel
|
||||
]
|
||||
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
||||
(Data.BookmarkedQuery.map (mkItem "fa fa-bookmark font-light" sel Collective) model.all.collective)
|
||||
]
|
||||
|
||||
|
||||
shares : Texts -> Model -> Selection -> Html Msg
|
||||
shares texts model sel =
|
||||
let
|
||||
bms =
|
||||
List.map shareToBookmark model.all.shares
|
||||
in
|
||||
div
|
||||
[ class ""
|
||||
, classList [ ( "hidden", List.isEmpty bms ) ]
|
||||
]
|
||||
[ div [ class " text-sm font-semibold py-0.5 " ]
|
||||
[ text texts.shareLabel
|
||||
]
|
||||
, div [ class "flex flex-col space-y-2 md:space-y-1" ]
|
||||
(List.map (mkItem Icons.share sel Share) bms)
|
||||
]
|
||||
|
||||
|
||||
mkItem : String -> Selection -> Kind -> BookmarkedQuery -> Html Msg
|
||||
mkItem icon sel kind bm =
|
||||
a
|
||||
[ class "flex flex-row items-center rounded px-1 py-1 hover:bg-blue-100 dark:hover:bg-slate-600"
|
||||
, href "#"
|
||||
, onClick (Toggle kind bm.name)
|
||||
]
|
||||
[ if isSelected sel kind bm.name then
|
||||
i [ class "fa fa-check" ] []
|
||||
|
||||
else
|
||||
i [ class icon ] []
|
||||
, span [ class "ml-2" ] [ text bm.name ]
|
||||
]
|
||||
|
||||
|
||||
isSelected : Selection -> Kind -> String -> Bool
|
||||
isSelected sel kind name =
|
||||
Set.member name <|
|
||||
case kind of
|
||||
User ->
|
||||
sel.user
|
||||
|
||||
Collective ->
|
||||
sel.collective
|
||||
|
||||
Share ->
|
||||
sel.shares
|
||||
|
||||
|
||||
shareToBookmark : ShareDetail -> BookmarkedQuery
|
||||
shareToBookmark share =
|
||||
BookmarkedQuery (Maybe.withDefault "-" share.name) share.query
|
@ -16,6 +16,7 @@ module Comp.SearchMenu exposing
|
||||
, isFulltextSearch
|
||||
, isNamesSearch
|
||||
, linkTargetMsg
|
||||
, refreshBookmarks
|
||||
, setFromStats
|
||||
, textSearchString
|
||||
, update
|
||||
@ -33,6 +34,7 @@ import Api.Model.ItemQuery exposing (ItemQuery)
|
||||
import Api.Model.PersonList exposing (PersonList)
|
||||
import Api.Model.ReferenceList exposing (ReferenceList)
|
||||
import Api.Model.SearchStats exposing (SearchStats)
|
||||
import Comp.BookmarkChooser
|
||||
import Comp.CustomFieldMultiInput
|
||||
import Comp.DatePicker
|
||||
import Comp.Dropdown exposing (isDropdownChangeMsg)
|
||||
@ -41,6 +43,7 @@ import Comp.LinkTarget exposing (LinkTarget)
|
||||
import Comp.MenuBar as MB
|
||||
import Comp.Tabs
|
||||
import Comp.TagSelect
|
||||
import Data.BookmarkedQuery exposing (AllBookmarks)
|
||||
import Data.CustomFieldChange exposing (CustomFieldValueCollect)
|
||||
import Data.Direction exposing (Direction)
|
||||
import Data.DropdownStyle as DS
|
||||
@ -96,6 +99,8 @@ type alias Model =
|
||||
, customFieldModel : Comp.CustomFieldMultiInput.Model
|
||||
, customValues : CustomFieldValueCollect
|
||||
, sourceModel : Maybe String
|
||||
, allBookmarks : Comp.BookmarkChooser.Model
|
||||
, selectedBookmarks : Comp.BookmarkChooser.Selection
|
||||
, openTabs : Set String
|
||||
, searchMode : SearchMode
|
||||
}
|
||||
@ -141,6 +146,8 @@ init flags =
|
||||
, customFieldModel = Comp.CustomFieldMultiInput.initWith []
|
||||
, customValues = Data.CustomFieldChange.emptyCollect
|
||||
, sourceModel = Nothing
|
||||
, allBookmarks = Comp.BookmarkChooser.init Data.BookmarkedQuery.allBookmarksEmpty
|
||||
, selectedBookmarks = Comp.BookmarkChooser.emptySelection
|
||||
, openTabs = Set.fromList [ "Tags", "Inbox" ]
|
||||
, searchMode = Data.SearchMode.Normal
|
||||
}
|
||||
@ -243,6 +250,10 @@ getItemQuery model =
|
||||
|
||||
textSearch =
|
||||
textSearchValue model.textSearchModel
|
||||
|
||||
bookmarks =
|
||||
List.map .query (Comp.BookmarkChooser.getQueries model.allBookmarks model.selectedBookmarks)
|
||||
|> List.map Q.Fragment
|
||||
in
|
||||
Q.and
|
||||
[ when model.inboxCheckbox (Q.Inbox True)
|
||||
@ -289,6 +300,7 @@ getItemQuery model =
|
||||
|> Maybe.map Q.Dir
|
||||
, textSearch.fullText
|
||||
|> Maybe.map Q.Contents
|
||||
, whenNotEmpty bookmarks Q.And
|
||||
]
|
||||
|
||||
|
||||
@ -333,6 +345,7 @@ resetModel model =
|
||||
model.customFieldModel
|
||||
, customValues = Data.CustomFieldChange.emptyCollect
|
||||
, sourceModel = Nothing
|
||||
, selectedBookmarks = Comp.BookmarkChooser.emptySelection
|
||||
, searchMode = Data.SearchMode.Normal
|
||||
}
|
||||
|
||||
@ -380,6 +393,8 @@ type Msg
|
||||
| GetAllTagsResp (Result Http.Error SearchStats)
|
||||
| ToggleAkkordionTab String
|
||||
| ToggleOpenAllAkkordionTabs
|
||||
| AllBookmarksResp (Result Http.Error AllBookmarks)
|
||||
| SelectBookmarkMsg Comp.BookmarkChooser.Msg
|
||||
|
||||
|
||||
setFromStats : SearchStats -> Msg
|
||||
@ -426,6 +441,11 @@ type alias NextState =
|
||||
}
|
||||
|
||||
|
||||
refreshBookmarks : Flags -> Cmd Msg
|
||||
refreshBookmarks flags =
|
||||
Api.getBookmarks flags AllBookmarksResp
|
||||
|
||||
|
||||
update : Flags -> UiSettings -> Msg -> Model -> NextState
|
||||
update =
|
||||
updateDrop DD.init
|
||||
@ -488,6 +508,7 @@ updateDrop ddm flags settings msg model =
|
||||
, Api.getPersons flags "" Data.PersonOrder.NameAsc GetPersonResp
|
||||
, Cmd.map CustomFieldMsg (Comp.CustomFieldMultiInput.initCmd flags)
|
||||
, cdp
|
||||
, Api.getBookmarks flags AllBookmarksResp
|
||||
]
|
||||
, stateChange = False
|
||||
, dragDrop = DD.DragDropData ddm Nothing
|
||||
@ -1040,6 +1061,31 @@ updateDrop ddm flags settings msg model =
|
||||
, dragDrop = DD.DragDropData ddm Nothing
|
||||
}
|
||||
|
||||
AllBookmarksResp (Ok bm) ->
|
||||
{ model = { model | allBookmarks = Comp.BookmarkChooser.init bm }
|
||||
, cmd = Cmd.none
|
||||
, stateChange = False
|
||||
, dragDrop = DD.DragDropData ddm Nothing
|
||||
}
|
||||
|
||||
AllBookmarksResp (Err err) ->
|
||||
{ model = model
|
||||
, cmd = Cmd.none
|
||||
, stateChange = False
|
||||
, dragDrop = DD.DragDropData ddm Nothing
|
||||
}
|
||||
|
||||
SelectBookmarkMsg lm ->
|
||||
let
|
||||
( next, sel ) =
|
||||
Comp.BookmarkChooser.update lm model.allBookmarks model.selectedBookmarks
|
||||
in
|
||||
{ model = { model | allBookmarks = next, selectedBookmarks = sel }
|
||||
, cmd = Cmd.none
|
||||
, stateChange = sel /= model.selectedBookmarks
|
||||
, dragDrop = DD.DragDropData ddm Nothing
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- View2
|
||||
@ -1064,6 +1110,7 @@ viewDrop2 texts ddd flags cfg settings model =
|
||||
|
||||
type SearchTab
|
||||
= TabInbox
|
||||
| TabBookmarks
|
||||
| TabTags
|
||||
| TabTagCategories
|
||||
| TabFolder
|
||||
@ -1080,6 +1127,7 @@ type SearchTab
|
||||
allTabs : List SearchTab
|
||||
allTabs =
|
||||
[ TabInbox
|
||||
, TabBookmarks
|
||||
, TabTags
|
||||
, TabTagCategories
|
||||
, TabFolder
|
||||
@ -1100,6 +1148,9 @@ tabName tab =
|
||||
TabInbox ->
|
||||
"inbox"
|
||||
|
||||
TabBookmarks ->
|
||||
"bookmarks"
|
||||
|
||||
TabTags ->
|
||||
"tags"
|
||||
|
||||
@ -1140,6 +1191,9 @@ findTab tab =
|
||||
"inbox" ->
|
||||
Just TabInbox
|
||||
|
||||
"bookmarks" ->
|
||||
Just TabBookmarks
|
||||
|
||||
"tags" ->
|
||||
Just TabTags
|
||||
|
||||
@ -1215,6 +1269,16 @@ tabLook settings model tab =
|
||||
TabInbox ->
|
||||
activeWhen model.inboxCheckbox
|
||||
|
||||
TabBookmarks ->
|
||||
if Comp.BookmarkChooser.isEmpty model.allBookmarks then
|
||||
Comp.Tabs.Hidden
|
||||
|
||||
else if not <| Comp.BookmarkChooser.isEmptySelection model.selectedBookmarks then
|
||||
Comp.Tabs.Active
|
||||
|
||||
else
|
||||
Comp.Tabs.Normal
|
||||
|
||||
TabTags ->
|
||||
hiddenOr [ Data.Fields.Tag ]
|
||||
(activeWhenNotEmpty model.tagSelection.includeTags model.tagSelection.excludeTags)
|
||||
@ -1329,52 +1393,15 @@ searchTabs texts ddd flags settings model =
|
||||
, label = texts.inbox
|
||||
, tagger = \_ -> ToggleInbox
|
||||
}
|
||||
, div [ class "mt-2 hidden" ]
|
||||
[ label [ class S.inputLabel ]
|
||||
[ text
|
||||
(case model.textSearchModel of
|
||||
Fulltext _ ->
|
||||
texts.fulltextSearch
|
||||
|
||||
Names _ ->
|
||||
texts.searchInNames
|
||||
)
|
||||
, a
|
||||
[ classList
|
||||
[ ( "hidden", not flags.config.fullTextSearchEnabled )
|
||||
]
|
||||
, class "float-right"
|
||||
, class S.link
|
||||
, href "#"
|
||||
, onClick SwapTextSearch
|
||||
, title texts.switchSearchModes
|
||||
]
|
||||
[ i [ class "fa fa-exchange-alt" ] []
|
||||
]
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetTextSearch
|
||||
, Util.Html.onKeyUpCode KeyUpMsg
|
||||
, textSearchString model.textSearchModel |> Maybe.withDefault "" |> value
|
||||
, case model.textSearchModel of
|
||||
Fulltext _ ->
|
||||
placeholder texts.contentSearch
|
||||
|
||||
Names _ ->
|
||||
placeholder texts.searchInNamesPlaceholder
|
||||
, class S.textInputSidebar
|
||||
]
|
||||
[]
|
||||
, span [ class "opacity-50 text-sm" ]
|
||||
[ case model.textSearchModel of
|
||||
Fulltext _ ->
|
||||
text texts.fulltextSearchInfo
|
||||
|
||||
Names _ ->
|
||||
text texts.nameSearchInfo
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
, { name = tabName TabBookmarks
|
||||
, title = texts.bookmarks
|
||||
, titleRight = []
|
||||
, info = Nothing
|
||||
, body =
|
||||
[ Html.map SelectBookmarkMsg
|
||||
(Comp.BookmarkChooser.view texts.bookmarkChooser model.allBookmarks model.selectedBookmarks)
|
||||
]
|
||||
}
|
||||
, { name = tabName TabTags
|
||||
|
Reference in New Issue
Block a user