mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-23 10:58:26 +00:00
Bookmark queries scoped to user or collective
This commit is contained in:
179
modules/webapp/src/main/elm/Comp/BookmarkQueryForm.elm
Normal file
179
modules/webapp/src/main/elm/Comp/BookmarkQueryForm.elm
Normal file
@ -0,0 +1,179 @@
|
||||
{-
|
||||
Copyright 2020 Eike K. & Contributors
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-}
|
||||
|
||||
|
||||
module Comp.BookmarkQueryForm exposing (Model, Msg, get, init, initQuery, update, view)
|
||||
|
||||
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 (..)
|
||||
import Html.Events exposing (onCheck, onInput)
|
||||
import Messages.Comp.BookmarkQueryForm exposing (Texts)
|
||||
import Styles as S
|
||||
import Util.Maybe
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ name : Maybe String
|
||||
, queryModel : Comp.PowerSearchInput.Model
|
||||
, location : Location
|
||||
}
|
||||
|
||||
|
||||
initQuery : String -> ( Model, Cmd Msg )
|
||||
initQuery q =
|
||||
let
|
||||
res =
|
||||
Comp.PowerSearchInput.update
|
||||
(Comp.PowerSearchInput.setSearchString q)
|
||||
Comp.PowerSearchInput.init
|
||||
in
|
||||
( { name = Nothing
|
||||
, queryModel = res.model
|
||||
, location = User
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Cmd.map QueryMsg res.cmd
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
init : ( Model, Cmd Msg )
|
||||
init =
|
||||
initQuery ""
|
||||
|
||||
|
||||
isValid : Model -> Bool
|
||||
isValid model =
|
||||
Comp.PowerSearchInput.isValid model.queryModel
|
||||
&& model.name
|
||||
/= Nothing
|
||||
|
||||
|
||||
get : Model -> Maybe BookmarkedQueryDef
|
||||
get model =
|
||||
let
|
||||
qStr =
|
||||
Maybe.withDefault "" model.queryModel.input
|
||||
in
|
||||
if isValid model then
|
||||
Just
|
||||
{ query =
|
||||
{ query = qStr
|
||||
, name = Maybe.withDefault "" model.name
|
||||
}
|
||||
, location = model.location
|
||||
}
|
||||
|
||||
else
|
||||
Nothing
|
||||
|
||||
|
||||
type Msg
|
||||
= SetName String
|
||||
| QueryMsg Comp.PowerSearchInput.Msg
|
||||
| SetLocation Location
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
|
||||
update _ msg model =
|
||||
case msg of
|
||||
SetName n ->
|
||||
( { model | name = Util.Maybe.fromString n }, Cmd.none, Sub.none )
|
||||
|
||||
SetLocation loc ->
|
||||
( { model | location = loc }, Cmd.none, Sub.none )
|
||||
|
||||
QueryMsg lm ->
|
||||
let
|
||||
res =
|
||||
Comp.PowerSearchInput.update lm model.queryModel
|
||||
in
|
||||
( { model | queryModel = res.model }
|
||||
, Cmd.map QueryMsg res.cmd
|
||||
, Sub.map QueryMsg res.subs
|
||||
)
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> Model -> Html Msg
|
||||
view texts model =
|
||||
let
|
||||
queryInput =
|
||||
div
|
||||
[ class "relative flex flex-grow flex-row" ]
|
||||
[ Html.map QueryMsg
|
||||
(Comp.PowerSearchInput.viewInput
|
||||
{ placeholder = texts.queryLabel
|
||||
, extraAttrs = []
|
||||
}
|
||||
model.queryModel
|
||||
)
|
||||
, Html.map QueryMsg
|
||||
(Comp.PowerSearchInput.viewResult [] model.queryModel)
|
||||
]
|
||||
in
|
||||
div
|
||||
[ class "flex flex-col" ]
|
||||
[ div [ class "mb-4" ]
|
||||
[ label
|
||||
[ for "sharename"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.basics.name
|
||||
, B.inputRequired
|
||||
]
|
||||
, input
|
||||
[ type_ "text"
|
||||
, onInput SetName
|
||||
, placeholder texts.basics.name
|
||||
, value <| Maybe.withDefault "" model.name
|
||||
, id "sharename"
|
||||
, class S.textInput
|
||||
]
|
||||
[]
|
||||
]
|
||||
, div [ class "flex flex-col mb-4 " ]
|
||||
[ label [ class "inline-flex items-center" ]
|
||||
[ input
|
||||
[ type_ "radio"
|
||||
, checked (model.location == User)
|
||||
, onCheck (\_ -> SetLocation User)
|
||||
, class S.radioInput
|
||||
]
|
||||
[]
|
||||
, span [ class "ml-2" ] [ text texts.userLocation ]
|
||||
, span [ class "ml-3 opacity-75 text-sm" ] [ text texts.userLocationText ]
|
||||
]
|
||||
, label [ class "inline-flex items-center" ]
|
||||
[ input
|
||||
[ type_ "radio"
|
||||
, checked (model.location == Collective)
|
||||
, class S.radioInput
|
||||
, onCheck (\_ -> SetLocation Collective)
|
||||
]
|
||||
[]
|
||||
, span [ class "ml-2" ] [ text texts.collectiveLocation ]
|
||||
, span [ class "ml-3 opacity-75 text-sm" ] [ text texts.collectiveLocationText ]
|
||||
]
|
||||
]
|
||||
, div [ class "mb-4" ]
|
||||
[ label
|
||||
[ for "sharequery"
|
||||
, class S.inputLabel
|
||||
]
|
||||
[ text texts.queryLabel
|
||||
, B.inputRequired
|
||||
]
|
||||
, queryInput
|
||||
]
|
||||
]
|
173
modules/webapp/src/main/elm/Comp/BookmarkQueryManage.elm
Normal file
173
modules/webapp/src/main/elm/Comp/BookmarkQueryManage.elm
Normal file
@ -0,0 +1,173 @@
|
||||
module Comp.BookmarkQueryManage exposing (..)
|
||||
|
||||
import Api
|
||||
import Api.Model.BasicResult exposing (BasicResult)
|
||||
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.Events exposing (onClick)
|
||||
import Http
|
||||
import Messages.Comp.BookmarkQueryManage exposing (Texts)
|
||||
import Styles as S
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ formModel : Comp.BookmarkQueryForm.Model
|
||||
, loading : Bool
|
||||
, formState : FormState
|
||||
}
|
||||
|
||||
|
||||
type FormState
|
||||
= FormStateNone
|
||||
| FormStateError Http.Error
|
||||
| FormStateSaveError String
|
||||
| FormStateInvalid
|
||||
| FormStateSaved
|
||||
|
||||
|
||||
init : String -> ( Model, Cmd Msg )
|
||||
init query =
|
||||
let
|
||||
( fm, fc ) =
|
||||
Comp.BookmarkQueryForm.initQuery query
|
||||
in
|
||||
( { formModel = fm
|
||||
, loading = False
|
||||
, formState = FormStateNone
|
||||
}
|
||||
, Cmd.map FormMsg fc
|
||||
)
|
||||
|
||||
|
||||
type Msg
|
||||
= Submit
|
||||
| Cancel
|
||||
| FormMsg Comp.BookmarkQueryForm.Msg
|
||||
| SaveResp (Result Http.Error BasicResult)
|
||||
|
||||
|
||||
|
||||
--- Update
|
||||
|
||||
|
||||
type FormResult
|
||||
= Submitted BookmarkedQueryDef
|
||||
| Cancelled
|
||||
| Done
|
||||
| None
|
||||
|
||||
|
||||
type alias UpdateResult =
|
||||
{ model : Model
|
||||
, cmd : Cmd Msg
|
||||
, sub : Sub Msg
|
||||
, outcome : FormResult
|
||||
}
|
||||
|
||||
|
||||
update : Flags -> Msg -> Model -> UpdateResult
|
||||
update flags msg model =
|
||||
let
|
||||
empty =
|
||||
{ model = model
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
, outcome = None
|
||||
}
|
||||
in
|
||||
case msg of
|
||||
FormMsg lm ->
|
||||
let
|
||||
( fm, fc, fs ) =
|
||||
Comp.BookmarkQueryForm.update flags lm model.formModel
|
||||
in
|
||||
{ model = { model | formModel = fm }
|
||||
, cmd = Cmd.map FormMsg fc
|
||||
, sub = Sub.map FormMsg fs
|
||||
, outcome = None
|
||||
}
|
||||
|
||||
Submit ->
|
||||
case Comp.BookmarkQueryForm.get model.formModel of
|
||||
Just data ->
|
||||
{ empty | cmd = save flags data, outcome = Submitted data, model = { model | loading = True } }
|
||||
|
||||
Nothing ->
|
||||
{ empty | model = { model | formState = FormStateInvalid } }
|
||||
|
||||
Cancel ->
|
||||
{ model = model
|
||||
, cmd = Cmd.none
|
||||
, sub = Sub.none
|
||||
, outcome = Cancelled
|
||||
}
|
||||
|
||||
SaveResp (Ok res) ->
|
||||
if res.success then
|
||||
{ empty | model = { model | loading = False, formState = FormStateSaved }, outcome = Done }
|
||||
|
||||
else
|
||||
{ empty | model = { model | loading = False, formState = FormStateSaveError res.message } }
|
||||
|
||||
SaveResp (Err err) ->
|
||||
{ empty | model = { model | loading = False, formState = FormStateError err } }
|
||||
|
||||
|
||||
save : Flags -> BookmarkedQueryDef -> Cmd Msg
|
||||
save flags model =
|
||||
Api.addBookmark flags model SaveResp
|
||||
|
||||
|
||||
|
||||
--- View
|
||||
|
||||
|
||||
view : Texts -> Model -> Html Msg
|
||||
view texts model =
|
||||
div [ class "relative" ]
|
||||
[ B.loadingDimmer { label = "", active = model.loading }
|
||||
, Html.map FormMsg (Comp.BookmarkQueryForm.view texts.form model.formModel)
|
||||
, case model.formState of
|
||||
FormStateNone ->
|
||||
div [ class "hidden" ] []
|
||||
|
||||
FormStateError err ->
|
||||
div [ class S.errorMessage ]
|
||||
[ text <| texts.httpError err
|
||||
]
|
||||
|
||||
FormStateInvalid ->
|
||||
div [ class S.errorMessage ]
|
||||
[ text texts.formInvalid
|
||||
]
|
||||
|
||||
FormStateSaveError m ->
|
||||
div [ class S.errorMessage ]
|
||||
[ text m
|
||||
]
|
||||
|
||||
FormStateSaved ->
|
||||
div [ class S.successMessage ]
|
||||
[ text texts.saved
|
||||
]
|
||||
, div [ class "flex flex-row space-x-2 py-2" ]
|
||||
[ B.primaryButton
|
||||
{ label = texts.basics.submit
|
||||
, icon = "fa fa-save"
|
||||
, disabled = False
|
||||
, handler = onClick Submit
|
||||
, attrs = [ href "#" ]
|
||||
}
|
||||
, B.secondaryButton
|
||||
{ label = texts.basics.cancel
|
||||
, icon = "fa fa-times"
|
||||
, disabled = False
|
||||
, handler = onClick Cancel
|
||||
, attrs = [ href "#" ]
|
||||
}
|
||||
]
|
||||
]
|
Reference in New Issue
Block a user