Instead of client only, make bookmarks a server aware feature

Makes it much more useful
This commit is contained in:
eikek
2022-01-09 23:50:34 +01:00
parent 063ae56488
commit 9415f72ec0
19 changed files with 618 additions and 345 deletions

View File

@ -11,8 +11,9 @@ module Comp.BookmarkChooser exposing
, view
)
import Api.Model.BookmarkedQuery exposing (BookmarkedQuery)
import Api.Model.ShareDetail exposing (ShareDetail)
import Data.BookmarkedQuery exposing (AllBookmarks, BookmarkedQuery)
import Data.Bookmarks exposing (AllBookmarks)
import Data.Icons as Icons
import Html exposing (Html, a, div, i, label, span, text)
import Html.Attributes exposing (class, classList, href)
@ -34,19 +35,18 @@ init all =
isEmpty : Model -> Bool
isEmpty model =
model.all == Data.BookmarkedQuery.allBookmarksEmpty
model.all == Data.Bookmarks.empty
type alias Selection =
{ user : Set String
, collective : Set String
{ bookmarks : Set String
, shares : Set String
}
emptySelection : Selection
emptySelection =
{ user = Set.empty, collective = Set.empty, shares = Set.empty }
{ bookmarks = Set.empty, shares = Set.empty }
isEmptySelection : Selection -> Bool
@ -55,8 +55,7 @@ isEmptySelection sel =
type Kind
= User
| Collective
= Bookmark
| Share
@ -68,14 +67,13 @@ getQueries : Model -> Selection -> List BookmarkedQuery
getQueries model sel =
let
member set bm =
Set.member bm.name set
Set.member bm.id set
filterBookmarks f bms =
Data.BookmarkedQuery.filter f bms |> Data.BookmarkedQuery.map identity
List.filter f bms |> List.map identity
in
List.concat
[ filterBookmarks (member sel.user) model.all.user
, filterBookmarks (member sel.collective) model.all.collective
[ filterBookmarks (member sel.bookmarks) model.all.bookmarks
, List.map shareToBookmark model.all.shares
|> List.filter (member sel.shares)
]
@ -96,16 +94,13 @@ update msg model current =
Set.insert name set
in
case msg of
Toggle kind name ->
Toggle kind id ->
case kind of
User ->
( model, { current | user = toggle name current.user } )
Collective ->
( model, { current | collective = toggle name current.collective } )
Bookmark ->
( model, { current | bookmarks = toggle id current.bookmarks } )
Share ->
( model, { current | shares = toggle name current.shares } )
( model, { current | shares = toggle id current.shares } )
@ -114,9 +109,13 @@ update msg model current =
view : Texts -> Model -> Selection -> Html Msg
view texts model selection =
let
( user, coll ) =
List.partition .personal model.all.bookmarks
in
div [ class "flex flex-col" ]
[ userBookmarks texts model selection
, collBookmarks texts model selection
[ userBookmarks texts user selection
, collBookmarks texts coll selection
, shares texts model selection
]
@ -130,27 +129,27 @@ titleDiv label =
]
userBookmarks : Texts -> Model -> Selection -> Html Msg
userBookmarks : Texts -> List BookmarkedQuery -> Selection -> Html Msg
userBookmarks texts model sel =
div
[ class "mb-2"
, classList [ ( "hidden", Data.BookmarkedQuery.emptyBookmarks == model.all.user ) ]
, classList [ ( "hidden", model == [] ) ]
]
[ titleDiv 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)
(List.map (mkItem "fa fa-bookmark" sel Bookmark) model)
]
collBookmarks : Texts -> Model -> Selection -> Html Msg
collBookmarks : Texts -> List BookmarkedQuery -> Selection -> Html Msg
collBookmarks texts model sel =
div
[ class "mb-2"
, classList [ ( "hidden", Data.BookmarkedQuery.emptyBookmarks == model.all.collective ) ]
, classList [ ( "hidden", [] == model ) ]
]
[ titleDiv 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)
(List.map (mkItem "fa fa-bookmark font-light" sel Bookmark) model)
]
@ -175,9 +174,9 @@ 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)
, onClick (Toggle kind bm.id)
]
[ if isSelected sel kind bm.name then
[ if isSelected sel kind bm.id then
i [ class "fa fa-check" ] []
else
@ -187,14 +186,11 @@ mkItem icon sel kind bm =
isSelected : Selection -> Kind -> String -> Bool
isSelected sel kind name =
Set.member name <|
isSelected sel kind id =
Set.member id <|
case kind of
User ->
sel.user
Collective ->
sel.collective
Bookmark ->
sel.bookmarks
Share ->
sel.shares
@ -202,4 +198,4 @@ isSelected sel kind name =
shareToBookmark : ShareDetail -> BookmarkedQuery
shareToBookmark share =
BookmarkedQuery (Maybe.withDefault "-" share.name) share.query
BookmarkedQuery share.id (Maybe.withDefault "-" share.name) share.name share.query False 0

View File

@ -14,7 +14,7 @@ import Comp.BookmarkQueryForm
import Comp.BookmarkTable
import Comp.ItemDetail.Model exposing (Msg(..))
import Comp.MenuBar as MB
import Data.BookmarkedQuery exposing (AllBookmarks)
import Data.Bookmarks exposing (AllBookmarks)
import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings)
import Html exposing (..)
@ -43,16 +43,10 @@ type DeleteConfirm
| DeleteConfirmOn
type alias FormData =
{ model : Comp.BookmarkQueryForm.Model
, oldName : Maybe String
}
type alias Model =
{ viewMode : ViewMode
, bookmarks : AllBookmarks
, formData : FormData
, formModel : Comp.BookmarkQueryForm.Model
, loading : Bool
, formError : FormError
, deleteConfirm : DeleteConfirm
@ -66,11 +60,8 @@ init flags =
Comp.BookmarkQueryForm.init
in
( { viewMode = Table
, bookmarks = Data.BookmarkedQuery.allBookmarksEmpty
, formData =
{ model = fm
, oldName = Nothing
}
, bookmarks = Data.Bookmarks.empty
, formModel = fm
, loading = False
, formError = FormErrorNone
, deleteConfirm = DeleteConfirmOff
@ -84,14 +75,14 @@ init flags =
type Msg
= LoadBookmarks
| TableMsg Data.BookmarkedQuery.Location Comp.BookmarkTable.Msg
| TableMsg Comp.BookmarkTable.Msg
| FormMsg Comp.BookmarkQueryForm.Msg
| InitNewBookmark
| SetViewMode ViewMode
| Submit
| RequestDelete
| CancelDelete
| DeleteBookmarkNow Data.BookmarkedQuery.Location String
| DeleteBookmarkNow String
| LoadBookmarksResp (Result Http.Error AllBookmarks)
| AddBookmarkResp (Result Http.Error BasicResult)
| UpdateBookmarkResp (Result Http.Error BasicResult)
@ -119,8 +110,7 @@ update flags msg model =
{ model
| viewMode = Form
, formError = FormErrorNone
, formData =
{ model = bm, oldName = Nothing }
, formModel = bm
}
in
( nm, Cmd.map FormMsg bc, Sub.none )
@ -138,14 +128,14 @@ update flags msg model =
FormMsg lm ->
let
( fm, fc, fs ) =
Comp.BookmarkQueryForm.update flags lm model.formData.model
Comp.BookmarkQueryForm.update flags lm model.formModel
in
( { model | formData = { model = fm, oldName = model.formData.oldName }, formError = FormErrorNone }
( { model | formModel = fm, formError = FormErrorNone }
, Cmd.map FormMsg fc
, Sub.map FormMsg fs
)
TableMsg loc lm ->
TableMsg lm ->
let
action =
Comp.BookmarkTable.update lm
@ -154,15 +144,12 @@ update flags msg model =
Comp.BookmarkTable.Edit bookmark ->
let
( bm, bc ) =
Comp.BookmarkQueryForm.initWith
{ query = bookmark
, location = loc
}
Comp.BookmarkQueryForm.initWith bookmark
in
( { model
| viewMode = Form
, formError = FormErrorNone
, formData = { model = bm, oldName = Just bookmark.name }
, formModel = bm
}
, Cmd.map FormMsg bc
, Sub.none
@ -174,9 +161,9 @@ update flags msg model =
CancelDelete ->
( { model | deleteConfirm = DeleteConfirmOff }, Cmd.none, Sub.none )
DeleteBookmarkNow loc name ->
DeleteBookmarkNow id ->
( { model | deleteConfirm = DeleteConfirmOff, loading = True }
, Api.deleteBookmark flags loc name DeleteBookmarkResp
, Api.deleteBookmark flags id DeleteBookmarkResp
, Sub.none
)
@ -196,14 +183,13 @@ update flags msg model =
( { model | loading = False, formError = FormErrorHttp err }, Cmd.none, Sub.none )
Submit ->
case Comp.BookmarkQueryForm.get model.formData.model of
case Comp.BookmarkQueryForm.get model.formModel of
Just data ->
case model.formData.oldName of
Just prevName ->
( { model | loading = True }, Api.updateBookmark flags prevName data AddBookmarkResp, Sub.none )
if data.id /= "" then
( { model | loading = True }, Api.updateBookmark flags data AddBookmarkResp, Sub.none )
Nothing ->
( { model | loading = True }, Api.addBookmark flags data AddBookmarkResp, Sub.none )
else
( { model | loading = True }, Api.addBookmark flags data AddBookmarkResp, Sub.none )
Nothing ->
( { model | formError = FormErrorInvalid }, Cmd.none, Sub.none )
@ -254,6 +240,10 @@ view texts settings flags model =
viewTable : Texts -> Model -> Html Msg
viewTable texts model =
let
( user, coll ) =
List.partition .personal model.bookmarks.bookmarks
in
div [ class "flex flex-col" ]
[ MB.view
{ start =
@ -268,17 +258,23 @@ viewTable texts model =
]
, rootClasses = "mb-4"
}
, div [ class "flex flex-col" ]
, div
[ class "flex flex-col"
, classList [ ( "hidden", user == [] ) ]
]
[ h3 [ class S.header3 ]
[ text texts.userBookmarks ]
, Html.map (TableMsg Data.BookmarkedQuery.User)
(Comp.BookmarkTable.view texts.bookmarkTable model.bookmarks.user)
, Html.map TableMsg
(Comp.BookmarkTable.view texts.bookmarkTable user)
]
, div
[ class "flex flex-col mt-3"
, classList [ ( "hidden", coll == [] ) ]
]
, div [ class "flex flex-col mt-3" ]
[ h3 [ class S.header3 ]
[ text texts.collectiveBookmarks ]
, Html.map (TableMsg Data.BookmarkedQuery.Collective)
(Comp.BookmarkTable.view texts.bookmarkTable model.bookmarks.collective)
, Html.map TableMsg
(Comp.BookmarkTable.view texts.bookmarkTable coll)
]
, B.loadingDimmer
{ label = ""
@ -291,10 +287,10 @@ viewForm : Texts -> UiSettings -> Flags -> Model -> Html Msg
viewForm texts _ _ model =
let
newBookmark =
model.formData.oldName == Nothing
model.formModel.bookmark.id == ""
isValid =
Comp.BookmarkQueryForm.get model.formData.model /= Nothing
Comp.BookmarkQueryForm.get model.formModel /= Nothing
in
div []
[ Html.form []
@ -305,7 +301,7 @@ viewForm texts _ _ model =
else
h1 [ class S.header2 ]
[ text (Maybe.withDefault "" model.formData.model.name)
[ text (Maybe.withDefault "" model.formModel.name)
]
, MB.view
{ start =
@ -360,7 +356,7 @@ viewForm texts _ _ model =
text m
]
, div []
[ Html.map FormMsg (Comp.BookmarkQueryForm.view texts.bookmarkForm model.formData.model)
[ Html.map FormMsg (Comp.BookmarkQueryForm.view texts.bookmarkForm model.formModel)
]
, B.loadingDimmer
{ active = model.loading
@ -378,11 +374,7 @@ viewForm texts _ _ model =
{ label = texts.basics.yes
, icon = "fa fa-check"
, disabled = False
, handler =
onClick
(DeleteBookmarkNow model.formData.model.location
(Maybe.withDefault "" model.formData.model.name)
)
, handler = onClick (DeleteBookmarkNow model.formModel.bookmark.id)
, attrs = [ href "#" ]
}
, B.secondaryButton

View File

@ -8,9 +8,9 @@
module Comp.BookmarkQueryForm exposing (Model, Msg, get, init, initQuery, initWith, update, view)
import Api
import Api.Model.BookmarkedQuery exposing (BookmarkedQuery)
import Comp.Basic as B
import Comp.PowerSearchInput
import Data.BookmarkedQuery exposing (BookmarkedQueryDef, Location(..))
import Data.Flags exposing (Flags)
import Html exposing (..)
import Html.Attributes exposing (..)
@ -24,10 +24,11 @@ import Util.Maybe
type alias Model =
{ name : Maybe String
{ bookmark : BookmarkedQuery
, name : Maybe String
, nameExists : Bool
, queryModel : Comp.PowerSearchInput.Model
, location : Location
, isPersonal : Bool
, nameExistsThrottle : Throttle Msg
}
@ -40,10 +41,11 @@ initQuery q =
(Comp.PowerSearchInput.setSearchString q)
Comp.PowerSearchInput.init
in
( { name = Nothing
( { bookmark = Api.Model.BookmarkedQuery.empty
, name = Nothing
, nameExists = False
, queryModel = res.model
, location = User
, isPersonal = True
, nameExistsThrottle = Throttle.create 1
}
, Cmd.batch
@ -57,15 +59,16 @@ init =
initQuery ""
initWith : BookmarkedQueryDef -> ( Model, Cmd Msg )
initWith : BookmarkedQuery -> ( Model, Cmd Msg )
initWith bm =
let
( m, c ) =
initQuery bm.query.query
initQuery bm.query
in
( { m
| name = Just bm.query.name
, location = bm.location
| name = Just bm.name
, isPersonal = bm.personal
, bookmark = bm
}
, c
)
@ -78,19 +81,21 @@ isValid model =
/= Nothing
get : Model -> Maybe BookmarkedQueryDef
get : Model -> Maybe BookmarkedQuery
get model =
let
qStr =
Maybe.withDefault "" model.queryModel.input
bm =
model.bookmark
in
if isValid model then
Just
{ query =
{ query = qStr
{ bm
| query = qStr
, name = Maybe.withDefault "" model.name
}
, location = model.location
, personal = model.isPersonal
}
else
@ -100,7 +105,7 @@ get model =
type Msg
= SetName String
| QueryMsg Comp.PowerSearchInput.Msg
| SetLocation Location
| SetPersonal Bool
| NameExistsResp (Result Http.Error Bool)
| UpdateThrottle
@ -109,12 +114,12 @@ update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
update flags msg model =
let
nameCheck1 name =
Api.bookmarkNameExists flags model.location name NameExistsResp
Api.bookmarkNameExists flags name NameExistsResp
nameCheck2 loc =
nameCheck2 =
case model.name of
Just n ->
Api.bookmarkNameExists flags loc n NameExistsResp
Api.bookmarkNameExists flags n NameExistsResp
Nothing ->
Cmd.none
@ -135,12 +140,12 @@ update flags msg model =
, throttleSub
)
SetLocation loc ->
SetPersonal flag ->
let
( newThrottle, cmd ) =
Throttle.try (nameCheck2 loc) model.nameExistsThrottle
Throttle.try nameCheck2 model.nameExistsThrottle
in
( { model | location = loc, nameExistsThrottle = newThrottle }, cmd, throttleSub )
( { model | isPersonal = flag, nameExistsThrottle = newThrottle }, cmd, throttleSub )
QueryMsg lm ->
let
@ -224,8 +229,8 @@ view texts model =
[ label [ class "inline-flex items-center" ]
[ input
[ type_ "radio"
, checked (model.location == User)
, onCheck (\_ -> SetLocation User)
, checked model.isPersonal
, onCheck (\_ -> SetPersonal True)
, class S.radioInput
]
[]
@ -235,9 +240,9 @@ view texts model =
, label [ class "inline-flex items-center" ]
[ input
[ type_ "radio"
, checked (model.location == Collective)
, checked (not model.isPersonal)
, class S.radioInput
, onCheck (\_ -> SetLocation Collective)
, onCheck (\_ -> SetPersonal False)
]
[]
, span [ class "ml-2" ] [ text texts.collectiveLocation ]

View File

@ -2,12 +2,12 @@ module Comp.BookmarkQueryManage exposing (..)
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.BookmarkedQuery exposing (BookmarkedQuery)
import Comp.Basic as B
import Comp.BookmarkQueryForm
import Data.BookmarkedQuery exposing (BookmarkedQueryDef)
import Data.Flags exposing (Flags)
import Html exposing (Html, div, text)
import Html.Attributes exposing (class, classList, href)
import Html.Attributes exposing (class, href)
import Html.Events exposing (onClick)
import Http
import Messages.Comp.BookmarkQueryManage exposing (Texts)
@ -55,7 +55,7 @@ type Msg
type FormResult
= Submitted BookmarkedQueryDef
= Submitted BookmarkedQuery
| Cancelled
| Done
| None
@ -117,7 +117,7 @@ update flags msg model =
{ empty | model = { model | loading = False, formState = FormStateError err } }
save : Flags -> BookmarkedQueryDef -> Cmd Msg
save : Flags -> BookmarkedQuery -> Cmd Msg
save flags model =
Api.addBookmark flags model SaveResp

View File

@ -12,8 +12,8 @@ module Comp.BookmarkTable exposing
, view
)
import Api.Model.BookmarkedQuery exposing (BookmarkedQuery)
import Comp.Basic as B
import Data.BookmarkedQuery exposing (BookmarkedQuery, Bookmarks)
import Html exposing (..)
import Html.Attributes exposing (..)
import Messages.Comp.BookmarkTable exposing (Texts)
@ -39,7 +39,7 @@ update msg =
--- View
view : Texts -> Bookmarks -> Html Msg
view : Texts -> List BookmarkedQuery -> Html Msg
view texts bms =
table [ class S.tableMain ]
[ thead []
@ -51,7 +51,7 @@ view texts bms =
]
]
, tbody []
(Data.BookmarkedQuery.map (renderBookmarkLine texts) bms)
(List.map (renderBookmarkLine texts) bms)
]

View File

@ -43,7 +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.Bookmarks exposing (AllBookmarks)
import Data.CustomFieldChange exposing (CustomFieldValueCollect)
import Data.Direction exposing (Direction)
import Data.DropdownStyle as DS
@ -146,7 +146,7 @@ init flags =
, customFieldModel = Comp.CustomFieldMultiInput.initWith []
, customValues = Data.CustomFieldChange.emptyCollect
, sourceModel = Nothing
, allBookmarks = Comp.BookmarkChooser.init Data.BookmarkedQuery.allBookmarksEmpty
, allBookmarks = Comp.BookmarkChooser.init Data.Bookmarks.empty
, selectedBookmarks = Comp.BookmarkChooser.emptySelection
, openTabs = Set.fromList [ "Tags", "Inbox" ]
, searchMode = Data.SearchMode.Normal