Files
docspell/modules/webapp/src/main/elm/Comp/OrgManage.elm
eikek cf88f5c2de Allow to specify ordering when retrieving meta data
The query now searches in more fields. For example, when getting a
list of tags, the query is applied to the tag name *and* category.
When listing persons, the query now also looks in the associated
organization name.

This has been used to make some headers in the meta data tables
clickable to sort the list accordingly.

Refs: #965, #538
2021-08-27 23:04:54 +02:00

373 lines
10 KiB
Elm

{-
Copyright 2020 Docspell Contributors
SPDX-License-Identifier: GPL-3.0-or-later
-}
module Comp.OrgManage exposing
( Model
, Msg(..)
, emptyModel
, update
, view2
)
import Api
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.Organization
import Api.Model.OrganizationList exposing (OrganizationList)
import Comp.Basic as B
import Comp.MenuBar as MB
import Comp.OrgForm
import Comp.OrgTable
import Comp.YesNoDimmer
import Data.Flags exposing (Flags)
import Data.OrganizationOrder exposing (OrganizationOrder)
import Data.UiSettings exposing (UiSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onSubmit)
import Http
import Messages.Comp.OrgManage exposing (Texts)
import Styles as S
import Util.Maybe
type alias Model =
{ tableModel : Comp.OrgTable.Model
, formModel : Comp.OrgForm.Model
, viewMode : ViewMode
, formError : FormError
, loading : Bool
, deleteConfirm : Comp.YesNoDimmer.Model
, query : String
, order : OrganizationOrder
}
type FormError
= FormErrorNone
| FormErrorHttp Http.Error
| FormErrorSubmit String
| FormErrorInvalid
type ViewMode
= Table
| Form
emptyModel : Model
emptyModel =
{ tableModel = Comp.OrgTable.emptyModel
, formModel = Comp.OrgForm.emptyModel
, viewMode = Table
, formError = FormErrorNone
, loading = False
, deleteConfirm = Comp.YesNoDimmer.emptyModel
, query = ""
, order = Data.OrganizationOrder.NameAsc
}
type Msg
= TableMsg Comp.OrgTable.Msg
| FormMsg Comp.OrgForm.Msg
| LoadOrgs
| OrgResp (Result Http.Error OrganizationList)
| SetViewMode ViewMode
| InitNewOrg
| Submit
| SubmitResp (Result Http.Error BasicResult)
| YesNoMsg Comp.YesNoDimmer.Msg
| RequestDelete
| SetQuery String
update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
update flags msg model =
case msg of
TableMsg m ->
let
( tm, tc, maybeOrder ) =
Comp.OrgTable.update flags m model.tableModel
( m2, c2 ) =
( { model
| tableModel = tm
, viewMode = Maybe.map (\_ -> Form) tm.selected |> Maybe.withDefault Table
, formError =
if Util.Maybe.nonEmpty tm.selected then
FormErrorNone
else
model.formError
, order = Maybe.withDefault model.order maybeOrder
}
, Cmd.map TableMsg tc
)
( m3, c3 ) =
case tm.selected of
Just org ->
update flags (FormMsg (Comp.OrgForm.SetOrg org)) m2
Nothing ->
( m2, Cmd.none )
( m4, c4 ) =
if maybeOrder /= Nothing && maybeOrder /= Just model.order then
update flags LoadOrgs m3
else
( m3, Cmd.none )
in
( m4, Cmd.batch [ c2, c3, c4 ] )
FormMsg m ->
let
( m2, c2 ) =
Comp.OrgForm.update flags m model.formModel
in
( { model | formModel = m2 }, Cmd.map FormMsg c2 )
LoadOrgs ->
( { model | loading = True }
, Api.getOrganizations
flags
model.query
model.order
OrgResp
)
OrgResp (Ok orgs) ->
let
m2 =
{ model | viewMode = Table, loading = False }
in
update flags (TableMsg (Comp.OrgTable.SetOrgs orgs.items)) m2
OrgResp (Err _) ->
( { model | loading = False }, Cmd.none )
SetViewMode m ->
let
m2 =
{ model | viewMode = m }
in
case m of
Table ->
update flags (TableMsg Comp.OrgTable.Deselect) m2
Form ->
( m2, Cmd.none )
InitNewOrg ->
let
nm =
{ model | viewMode = Form, formError = FormErrorNone }
org =
Api.Model.Organization.empty
in
update flags (FormMsg (Comp.OrgForm.SetOrg org)) nm
Submit ->
let
org =
Comp.OrgForm.getOrg model.formModel
valid =
Comp.OrgForm.isValid model.formModel
in
if valid then
( { model | loading = True }, Api.postOrg flags org SubmitResp )
else
( { model | formError = FormErrorInvalid }, Cmd.none )
SubmitResp (Ok res) ->
if res.success then
let
( m2, c2 ) =
update flags (SetViewMode Table) model
( m3, c3 ) =
update flags LoadOrgs m2
in
( { m3 | loading = False }, Cmd.batch [ c2, c3 ] )
else
( { model | formError = FormErrorSubmit res.message, loading = False }, Cmd.none )
SubmitResp (Err err) ->
( { model | formError = FormErrorHttp err, loading = False }, Cmd.none )
RequestDelete ->
update flags (YesNoMsg Comp.YesNoDimmer.activate) model
YesNoMsg m ->
let
( cm, confirmed ) =
Comp.YesNoDimmer.update m model.deleteConfirm
org =
Comp.OrgForm.getOrg model.formModel
cmd =
if confirmed then
Api.deleteOrg flags org.id SubmitResp
else
Cmd.none
in
( { model | deleteConfirm = cm }, cmd )
SetQuery str ->
let
m =
{ model | query = str }
in
( m, Api.getOrganizations flags str model.order OrgResp )
--- View2
view2 : Texts -> UiSettings -> Model -> Html Msg
view2 texts settings model =
if model.viewMode == Table then
viewTable2 texts model
else
viewForm2 texts settings model
viewTable2 : Texts -> Model -> Html Msg
viewTable2 texts model =
div [ class "flex flex-col relative" ]
[ MB.view
{ start =
[ MB.TextInput
{ tagger = SetQuery
, value = model.query
, placeholder = texts.basics.searchPlaceholder
, icon = Just "fa fa-search"
}
]
, end =
[ MB.PrimaryButton
{ tagger = InitNewOrg
, title = texts.createNewOrganization
, icon = Just "fa fa-plus"
, label = texts.newOrganization
}
]
, rootClasses = "mb-4"
}
, Html.map TableMsg (Comp.OrgTable.view2 texts.orgTable model.order model.tableModel)
, B.loadingDimmer
{ active = model.loading
, label = texts.basics.loading
}
]
viewForm2 : Texts -> UiSettings -> Model -> Html Msg
viewForm2 texts settings model =
let
newOrg =
model.formModel.org.id == ""
dimmerSettings2 =
Comp.YesNoDimmer.defaultSettings texts.reallyDeleteOrg
texts.basics.yes
texts.basics.no
in
Html.form
[ class "md:relative flex flex-col"
, onSubmit Submit
]
[ Html.map YesNoMsg
(Comp.YesNoDimmer.viewN
True
dimmerSettings2
model.deleteConfirm
)
, if newOrg then
h3 [ class S.header2 ]
[ text texts.createNewOrganization
]
else
h3 [ class S.header2 ]
[ text model.formModel.org.name
, div [ class "opacity-50 text-sm" ]
[ text (texts.basics.id ++ ": ")
, text model.formModel.org.id
]
]
, MB.view
{ start =
[ MB.PrimaryButton
{ tagger = Submit
, title = texts.basics.submitThisForm
, icon = Just "fa fa-save"
, label = texts.basics.submit
}
, MB.SecondaryButton
{ tagger = SetViewMode Table
, title = texts.basics.backToList
, icon = Just "fa fa-arrow-left"
, label = texts.basics.cancel
}
]
, end =
if not newOrg then
[ MB.DeleteButton
{ tagger = RequestDelete
, title = texts.deleteThisOrg
, icon = Just "fa fa-trash"
, label = texts.basics.delete
}
]
else
[]
, rootClasses = "mb-4"
}
, div
[ classList
[ ( "hidden", model.formError == FormErrorNone )
]
, class S.errorMessage
, class "my-2"
]
[ case model.formError of
FormErrorNone ->
text ""
FormErrorSubmit m ->
text m
FormErrorHttp err ->
text (texts.httpError err)
FormErrorInvalid ->
text texts.correctFormErrors
]
, Html.map FormMsg
(Comp.OrgForm.view2
texts.orgForm
False
settings
model.formModel
)
, B.loadingDimmer
{ active = model.loading
, label = texts.basics.loading
}
]