diff --git a/modules/webapp/src/main/elm/Api.elm b/modules/webapp/src/main/elm/Api.elm index 9d5c9e84..6d46e15b 100644 --- a/modules/webapp/src/main/elm/Api.elm +++ b/modules/webapp/src/main/elm/Api.elm @@ -16,6 +16,7 @@ module Api exposing , addTag , addTagsMultiple , attachmentPreviewURL + , bookmarkNameExists , cancelJob , changeFolderName , changePassword @@ -2371,6 +2372,23 @@ addBookmark flags model receive = Task.andThen add load |> Task.attempt receive +bookmarkNameExistsTask : Flags -> BookmarkLocation -> String -> Task.Task Http.Error Bool +bookmarkNameExistsTask flags loc name = + let + load = + getBookmarksTask flags loc + + exists current = + Data.BookmarkedQuery.exists name current + in + Task.map exists load + + +bookmarkNameExists : Flags -> BookmarkLocation -> String -> (Result Http.Error Bool -> msg) -> Cmd msg +bookmarkNameExists flags loc name receive = + bookmarkNameExistsTask flags loc name |> Task.attempt receive + + --- OTP diff --git a/modules/webapp/src/main/elm/Comp/BookmarkQueryForm.elm b/modules/webapp/src/main/elm/Comp/BookmarkQueryForm.elm index 95456356..7485a5bb 100644 --- a/modules/webapp/src/main/elm/Comp/BookmarkQueryForm.elm +++ b/modules/webapp/src/main/elm/Comp/BookmarkQueryForm.elm @@ -7,6 +7,7 @@ module Comp.BookmarkQueryForm exposing (Model, Msg, get, init, initQuery, update, view) +import Api import Comp.Basic as B import Comp.PowerSearchInput import Data.BookmarkedQuery exposing (BookmarkedQueryDef, Location(..)) @@ -14,15 +15,20 @@ import Data.Flags exposing (Flags) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onCheck, onInput) +import Http import Messages.Comp.BookmarkQueryForm exposing (Texts) import Styles as S +import Throttle exposing (Throttle) +import Time import Util.Maybe type alias Model = { name : Maybe String + , nameExists : Bool , queryModel : Comp.PowerSearchInput.Model , location : Location + , nameExistsThrottle : Throttle Msg } @@ -35,8 +41,10 @@ initQuery q = Comp.PowerSearchInput.init in ( { name = Nothing + , nameExists = False , queryModel = res.model , location = User + , nameExistsThrottle = Throttle.create 1 } , Cmd.batch [ Cmd.map QueryMsg res.cmd @@ -79,16 +87,46 @@ type Msg = SetName String | QueryMsg Comp.PowerSearchInput.Msg | SetLocation Location + | NameExistsResp (Result Http.Error Bool) + | UpdateThrottle update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) -update _ msg model = +update flags msg model = + let + nameCheck1 name = + Api.bookmarkNameExists flags model.location name NameExistsResp + + nameCheck2 loc = + case model.name of + Just n -> + Api.bookmarkNameExists flags loc n NameExistsResp + + Nothing -> + Cmd.none + + throttleSub = + Throttle.ifNeeded + (Time.every 150 (\_ -> UpdateThrottle)) + model.nameExistsThrottle + in case msg of SetName n -> - ( { model | name = Util.Maybe.fromString n }, Cmd.none, Sub.none ) + let + ( newThrottle, cmd ) = + Throttle.try (nameCheck1 n) model.nameExistsThrottle + in + ( { model | name = Util.Maybe.fromString n, nameExistsThrottle = newThrottle } + , cmd + , throttleSub + ) SetLocation loc -> - ( { model | location = loc }, Cmd.none, Sub.none ) + let + ( newThrottle, cmd ) = + Throttle.try (nameCheck2 loc) model.nameExistsThrottle + in + ( { model | location = loc, nameExistsThrottle = newThrottle }, cmd, throttleSub ) QueryMsg lm -> let @@ -100,6 +138,25 @@ update _ msg model = , Sub.map QueryMsg res.subs ) + NameExistsResp (Ok flag) -> + ( { model | nameExists = flag } + , Cmd.none + , Sub.none + ) + + NameExistsResp (Err err) -> + ( model, Cmd.none, Sub.none ) + + UpdateThrottle -> + let + ( newThrottle, cmd ) = + Throttle.update model.nameExistsThrottle + in + ( { model | nameExistsThrottle = newThrottle } + , cmd + , throttleSub + ) + --- View @@ -124,9 +181,9 @@ view texts model = in div [ class "flex flex-col" ] - [ div [ class "mb-4" ] + [ div [ class "mb-2" ] [ label - [ for "sharename" + [ for "bookmark-name" , class S.inputLabel ] [ text texts.basics.name @@ -137,10 +194,17 @@ view texts model = , onInput SetName , placeholder texts.basics.name , value <| Maybe.withDefault "" model.name - , id "sharename" + , id "bookmark-name" , class S.textInput ] [] + , span + [ class S.infoMessagePlain + , class "font-medium text-sm" + , classList [ ( "invisible", not model.nameExists ) ] + ] + [ text texts.nameExistsWarning + ] ] , div [ class "flex flex-col mb-4 " ] [ label [ class "inline-flex items-center" ] diff --git a/modules/webapp/src/main/elm/Messages/Comp/BookmarkQueryForm.elm b/modules/webapp/src/main/elm/Messages/Comp/BookmarkQueryForm.elm index 1fcf3fa4..34639a5d 100644 --- a/modules/webapp/src/main/elm/Messages/Comp/BookmarkQueryForm.elm +++ b/modules/webapp/src/main/elm/Messages/Comp/BookmarkQueryForm.elm @@ -21,6 +21,7 @@ type alias Texts = , userLocationText : String , collectiveLocation : String , collectiveLocationText : String + , nameExistsWarning : String } @@ -32,6 +33,7 @@ gb = , userLocationText = "The bookmarked query is just for you" , collectiveLocation = "Collective scope" , collectiveLocationText = "The bookmarked query can be used and edited by all users" + , nameExistsWarning = "A bookmark with this name exists, it is overwritten on save!" } @@ -43,4 +45,5 @@ de = , userLocationText = "Der Bookmark ist nur für dich" , collectiveLocation = "Kollektiv-Bookmark" , collectiveLocationText = "Der Bookmark kann von allen Benutzer verwendet werden" + , nameExistsWarning = "Der Bookmark existiert bereits. Er wird beim Speichern überschrieben." } diff --git a/modules/webapp/src/main/elm/Styles.elm b/modules/webapp/src/main/elm/Styles.elm index abea7a25..314f8dc7 100644 --- a/modules/webapp/src/main/elm/Styles.elm +++ b/modules/webapp/src/main/elm/Styles.elm @@ -55,6 +55,11 @@ errorText = " text-red-600 dark:text-orange-800 " +warnMessagePlain : String +warnMessagePlain = + " text-yellow-800 dark:text-amber-200 " + + warnMessage : String warnMessage = warnMessageColors ++ " border dark:bg-opacity-25 px-2 py-2 rounded " @@ -62,12 +67,17 @@ warnMessage = warnMessageColors : String warnMessageColors = - " border-yellow-800 bg-yellow-50 text-yellow-800 dark:border-amber-200 dark:bg-amber-800 dark:text-amber-200 " + warnMessagePlain ++ " border-yellow-800 bg-yellow-50 dark:border-amber-200 dark:bg-amber-800 " + + +infoMessagePlain : String +infoMessagePlain = + " text-blue-800 dark:text-sky-200 " infoMessageBase : String infoMessageBase = - " border border-blue-800 bg-blue-100 text-blue-800 dark:border-sky-200 dark:bg-sky-800 dark:text-sky-200 dark:bg-opacity-25 " + infoMessagePlain ++ " border border-blue-800 bg-blue-100 dark:border-sky-200 dark:bg-sky-800 dark:bg-opacity-25 " infoMessage : String