Add ui for showing data to be deleted for a user

This commit is contained in:
eikek 2021-09-08 00:22:00 +02:00
parent e89b571ab2
commit a94aeff75c
5 changed files with 179 additions and 49 deletions

View File

@ -43,7 +43,6 @@ module Api exposing
, deleteSource , deleteSource
, deleteTag , deleteTag
, deleteUser , deleteUser
, deleteUserData
, disableOtp , disableOtp
, fileURL , fileURL
, getAttachmentMeta , getAttachmentMeta
@ -52,6 +51,7 @@ module Api exposing
, getCollectiveSettings , getCollectiveSettings
, getContacts , getContacts
, getCustomFields , getCustomFields
, getDeleteUserData
, getEquipment , getEquipment
, getEquipments , getEquipments
, getFolderDetail , getFolderDetail
@ -1469,8 +1469,8 @@ deleteUser flags user receive =
} }
deleteUserData : Flags -> String -> (Result Http.Error DeleteUserData -> msg) -> Cmd msg getDeleteUserData : Flags -> String -> (Result Http.Error DeleteUserData -> msg) -> Cmd msg
deleteUserData flags username receive = getDeleteUserData flags username receive =
Http2.authGet Http2.authGet
{ url = flags.config.baseUrl ++ "/api/v1/sec/user/" ++ username ++ "/deleteData" { url = flags.config.baseUrl ++ "/api/v1/sec/user/" ++ username ++ "/deleteData"
, account = getAccount flags , account = getAccount flags

View File

@ -6,7 +6,9 @@
module Comp.Basic exposing module Comp.Basic exposing
( editLinkLabel ( contentDimmer
, deleteButton
, editLinkLabel
, editLinkTableCell , editLinkTableCell
, genericButton , genericButton
, horizontalDivider , horizontalDivider
@ -89,6 +91,27 @@ secondaryButton model =
} }
deleteButton :
{ x
| label : String
, icon : String
, disabled : Bool
, handler : Attribute msg
, attrs : List (Attribute msg)
}
-> Html msg
deleteButton model =
genericButton
{ label = model.label
, icon = model.icon
, handler = model.handler
, disabled = model.disabled
, attrs = model.attrs
, baseStyle = S.deleteButtonMain
, activeStyle = S.deleteButtonHover
}
secondaryBasicButton : secondaryBasicButton :
{ x { x
| label : String | label : String
@ -182,18 +205,27 @@ linkLabel model =
loadingDimmer : { label : String, active : Bool } -> Html msg loadingDimmer : { label : String, active : Bool } -> Html msg
loadingDimmer cfg = loadingDimmer cfg =
let
content =
div [ class "text-gray-200" ]
[ i [ class "fa fa-circle-notch animate-spin" ] []
, span [ class "ml-2" ]
[ text cfg.label
]
]
in
contentDimmer cfg.active content
contentDimmer : Bool -> Html msg -> Html msg
contentDimmer active content =
div div
[ classList [ classList
[ ( "hidden", not cfg.active ) [ ( "hidden", not active )
] ]
, class S.dimmer , class S.dimmer
] ]
[ div [ class "text-gray-200" ] [ content
[ i [ class "fa fa-circle-notch animate-spin" ] []
, span [ class "ml-2" ]
[ text cfg.label
]
]
] ]

View File

@ -15,18 +15,18 @@ module Comp.UserManage exposing
import Api import Api
import Api.Model.BasicResult exposing (BasicResult) import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.DeleteUserData exposing (DeleteUserData)
import Api.Model.User import Api.Model.User
import Api.Model.UserList exposing (UserList) import Api.Model.UserList exposing (UserList)
import Comp.Basic as B import Comp.Basic as B
import Comp.MenuBar as MB import Comp.MenuBar as MB
import Comp.UserForm import Comp.UserForm
import Comp.UserTable import Comp.UserTable
import Comp.YesNoDimmer
import Data.Flags exposing (Flags) import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings) import Data.UiSettings exposing (UiSettings)
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (..) import Html.Attributes exposing (..)
import Html.Events exposing (onSubmit) import Html.Events exposing (onClick, onSubmit)
import Http import Http
import Messages.Comp.UserManage exposing (Texts) import Messages.Comp.UserManage exposing (Texts)
import Styles as S import Styles as S
@ -39,10 +39,16 @@ type alias Model =
, viewMode : ViewMode , viewMode : ViewMode
, formError : FormError , formError : FormError
, loading : Bool , loading : Bool
, deleteConfirm : Comp.YesNoDimmer.Model , deleteConfirm : DimmerMode
} }
type DimmerMode
= DimmerOff
| DimmerLoading
| DimmerUserData DeleteUserData
type ViewMode type ViewMode
= Table = Table
| Form | Form
@ -53,6 +59,7 @@ type FormError
| FormErrorSubmit String | FormErrorSubmit String
| FormErrorHttp Http.Error | FormErrorHttp Http.Error
| FormErrorInvalid | FormErrorInvalid
| FormErrorCurrentUser
emptyModel : Model emptyModel : Model
@ -62,7 +69,7 @@ emptyModel =
, viewMode = Table , viewMode = Table
, formError = FormErrorNone , formError = FormErrorNone
, loading = False , loading = False
, deleteConfirm = Comp.YesNoDimmer.emptyModel , deleteConfirm = DimmerOff
} }
@ -75,8 +82,10 @@ type Msg
| InitNewUser | InitNewUser
| Submit | Submit
| SubmitResp (Result Http.Error BasicResult) | SubmitResp (Result Http.Error BasicResult)
| YesNoMsg Comp.YesNoDimmer.Msg
| RequestDelete | RequestDelete
| GetDeleteDataResp (Result Http.Error DeleteUserData)
| DeleteUserNow String
| CancelDelete
update : Flags -> Msg -> Model -> ( Model, Cmd Msg ) update : Flags -> Msg -> Model -> ( Model, Cmd Msg )
@ -183,12 +192,44 @@ update flags msg model =
( m3, c3 ) = ( m3, c3 ) =
update flags LoadUsers m2 update flags LoadUsers m2
in in
( { m3 | loading = False }, Cmd.batch [ c2, c3 ] ) ( { m3 | loading = False, deleteConfirm = DimmerOff }, Cmd.batch [ c2, c3 ] )
else else
( { model | formError = FormErrorSubmit res.message, loading = False }, Cmd.none ) ( { model
| formError = FormErrorSubmit res.message
, loading = False
, deleteConfirm = DimmerOff
}
, Cmd.none
)
SubmitResp (Err err) -> SubmitResp (Err err) ->
( { model
| formError = FormErrorHttp err
, loading = False
, deleteConfirm = DimmerOff
}
, Cmd.none
)
RequestDelete ->
let
login =
Maybe.map .user flags.account
|> Maybe.withDefault ""
in
if model.formModel.user.login == login then
( { model | formError = FormErrorCurrentUser }, Cmd.none )
else
( { model | deleteConfirm = DimmerLoading }
, Api.getDeleteUserData flags model.formModel.user.login GetDeleteDataResp
)
GetDeleteDataResp (Ok data) ->
( { model | deleteConfirm = DimmerUserData data }, Cmd.none )
GetDeleteDataResp (Err err) ->
( { model ( { model
| formError = FormErrorHttp err | formError = FormErrorHttp err
, loading = False , loading = False
@ -196,29 +237,15 @@ update flags msg model =
, Cmd.none , Cmd.none
) )
RequestDelete -> CancelDelete ->
update flags (YesNoMsg Comp.YesNoDimmer.activate) model ( { model | deleteConfirm = DimmerOff }, Cmd.none )
YesNoMsg m -> DeleteUserNow login ->
let ( { model | deleteConfirm = DimmerLoading }, Api.deleteUser flags login SubmitResp )
( cm, confirmed ) =
Comp.YesNoDimmer.update m model.deleteConfirm
user =
Comp.UserForm.getUser model.formModel
cmd =
if confirmed then
Api.deleteUser flags user.login SubmitResp
else
Cmd.none
in
( { model | deleteConfirm = cm }, cmd )
--- View2 --- View
view2 : Texts -> UiSettings -> Model -> Html Msg view2 : Texts -> UiSettings -> Model -> Html Msg
@ -253,27 +280,82 @@ viewTable2 texts model =
] ]
renderDeleteConfirm : Texts -> UiSettings -> Model -> Html Msg
renderDeleteConfirm texts settings model =
case model.deleteConfirm of
DimmerOff ->
span [ class "hidden" ] []
DimmerLoading ->
B.loadingDimmer
{ label = "Loading..."
, active = True
}
DimmerUserData data ->
let
empty =
List.isEmpty data.folders && data.sentMails == 0
folderNames =
String.join ", " data.folders
in
B.contentDimmer True <|
div [ class "flex flex-col" ] <|
(if empty then
[ div []
[ text texts.reallyDeleteUser
]
]
else
[ div []
[ text texts.reallyDeleteUser
, text " "
, text "The following data will be deleted:"
]
, ul [ class "list-inside list-disc" ]
[ li [ classList [ ( "hidden", List.isEmpty data.folders ) ] ]
[ text "Folders: "
, text folderNames
]
, li [ classList [ ( "hidden", data.sentMails == 0 ) ] ]
[ text (String.fromInt data.sentMails)
, text " sent mails"
]
]
]
)
++ [ div [ class "mt-4 flex flex-row items-center" ]
[ B.deleteButton
{ label = texts.basics.yes
, icon = "fa fa-check"
, disabled = False
, handler = onClick (DeleteUserNow model.formModel.user.login)
, attrs = [ href "#" ]
}
, B.secondaryButton
{ label = texts.basics.no
, icon = "fa fa-times"
, disabled = False
, handler = onClick CancelDelete
, attrs = [ href "#", class "ml-2" ]
}
]
]
viewForm2 : Texts -> UiSettings -> Model -> Html Msg viewForm2 : Texts -> UiSettings -> Model -> Html Msg
viewForm2 texts settings model = viewForm2 texts settings model =
let let
newUser = newUser =
Comp.UserForm.isNewUser model.formModel Comp.UserForm.isNewUser model.formModel
dimmerSettings : Comp.YesNoDimmer.Settings
dimmerSettings =
Comp.YesNoDimmer.defaultSettings texts.reallyDeleteUser
texts.basics.yes
texts.basics.no
in in
Html.form Html.form
[ class "flex flex-col md:relative" [ class "flex flex-col md:relative"
, onSubmit Submit , onSubmit Submit
] ]
[ Html.map YesNoMsg [ renderDeleteConfirm texts settings model
(Comp.YesNoDimmer.viewN True
dimmerSettings
model.deleteConfirm
)
, if newUser then , if newUser then
h3 [ class S.header2 ] h3 [ class S.header2 ]
[ text texts.createNewUser [ text texts.createNewUser
@ -331,6 +413,9 @@ viewForm2 texts settings model =
FormErrorInvalid -> FormErrorInvalid ->
text texts.pleaseCorrectErrors text texts.pleaseCorrectErrors
FormErrorCurrentUser ->
text texts.notDeleteCurrentUser
] ]
, B.loadingDimmer , B.loadingDimmer
{ active = model.loading { active = model.loading

View File

@ -30,6 +30,7 @@ type alias Texts =
, basics : Messages.Basics.Texts , basics : Messages.Basics.Texts
, deleteThisUser : String , deleteThisUser : String
, pleaseCorrectErrors : String , pleaseCorrectErrors : String
, notDeleteCurrentUser : String
} }
@ -46,6 +47,7 @@ gb =
, createNewUser = "Create new user" , createNewUser = "Create new user"
, deleteThisUser = "Delete this user" , deleteThisUser = "Delete this user"
, pleaseCorrectErrors = "Please correct the errors in the form." , pleaseCorrectErrors = "Please correct the errors in the form."
, notDeleteCurrentUser = "You can't delete the user you are currently logged in with."
} }
@ -62,4 +64,5 @@ de =
, createNewUser = "Neuen Benutzer erstellen" , createNewUser = "Neuen Benutzer erstellen"
, deleteThisUser = "Benutzer löschen" , deleteThisUser = "Benutzer löschen"
, pleaseCorrectErrors = "Bitte korrigiere die Fehler im Formular." , pleaseCorrectErrors = "Bitte korrigiere die Fehler im Formular."
, notDeleteCurrentUser = "Der aktuelle Benutzer kann nicht gelöscht werden."
} }

View File

@ -197,7 +197,17 @@ secondaryBasicButtonHover =
deleteButton : String deleteButton : String
deleteButton = deleteButton =
" rounded my-auto whitespace-nowrap border border-red-500 dark:border-lightred-500 text-red-500 dark:text-orange-500 text-center px-4 py-2 shadow-none focus:outline-none focus:ring focus:ring-opacity-75 hover:bg-red-600 hover:text-white dark:hover:text-white dark:hover:bg-orange-500 dark:hover:text-bluegray-900 " deleteButtonMain ++ deleteButtonHover
deleteButtonMain : String
deleteButtonMain =
" rounded my-auto whitespace-nowrap border border-red-500 dark:border-lightred-500 text-red-500 dark:text-orange-500 text-center px-4 py-2 shadow-none focus:outline-none focus:ring focus:ring-opacity-75 "
deleteButtonHover : String
deleteButtonHover =
" hover:bg-red-600 hover:text-white dark:hover:bg-orange-500 dark:hover:text-bluegray-900 "
undeleteButton : String undeleteButton : String