Support Admins inviting users from the client
The title says it all.
This commit is contained in:
parent
a3d783025a
commit
1d5cf2e4b5
2 changed files with 139 additions and 1 deletions
|
@ -5,6 +5,7 @@ import Date
|
|||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (..)
|
||||
import Maybe.Extra as ME
|
||||
import RemoteData
|
||||
import State
|
||||
import Tailwind
|
||||
|
@ -12,6 +13,59 @@ import UI
|
|||
import Utils
|
||||
|
||||
|
||||
roleToggle : State.Model -> State.Role -> Html State.Msg
|
||||
roleToggle model role =
|
||||
div [ [ "px-1", "inline" ] |> Tailwind.use |> class ]
|
||||
[ UI.toggleButton
|
||||
{ toggled = model.inviteRole == Just role
|
||||
, label = State.roleToString role
|
||||
, handleEnable = State.UpdateInviteRole (Just role)
|
||||
, handleDisable = State.UpdateInviteRole Nothing
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
inviteUser : State.Model -> Html State.Msg
|
||||
inviteUser model =
|
||||
div [ [ "pb-6" ] |> Tailwind.use |> class ]
|
||||
[ UI.header 3 "Invite a user"
|
||||
, UI.textField
|
||||
{ handleInput = State.UpdateInviteEmail
|
||||
, inputId = "invite-email"
|
||||
, inputValue = model.inviteEmail
|
||||
, pholder = "Email..."
|
||||
}
|
||||
, div [ [ "pt-4" ] |> Tailwind.use |> class ]
|
||||
[ roleToggle model State.User
|
||||
, roleToggle model State.Manager
|
||||
, roleToggle model State.Admin
|
||||
]
|
||||
, UI.baseButton
|
||||
{ enabled =
|
||||
List.all
|
||||
identity
|
||||
[ String.length model.inviteEmail > 0
|
||||
, ME.isJust model.inviteRole
|
||||
]
|
||||
, extraClasses = [ "my-4" ]
|
||||
, label =
|
||||
case model.inviteResponseStatus of
|
||||
RemoteData.Loading ->
|
||||
"Sending..."
|
||||
|
||||
_ ->
|
||||
"Send invitation"
|
||||
, handleClick =
|
||||
case model.inviteRole of
|
||||
Nothing ->
|
||||
State.DoNothing
|
||||
|
||||
Just role ->
|
||||
State.AttemptInviteUser role
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
allTrips : State.Model -> Html State.Msg
|
||||
allTrips model =
|
||||
case model.trips of
|
||||
|
@ -124,7 +178,10 @@ render model =
|
|||
]
|
||||
, case model.adminTab of
|
||||
State.Accounts ->
|
||||
allUsers model
|
||||
div []
|
||||
[ inviteUser model
|
||||
, allUsers model
|
||||
]
|
||||
|
||||
State.Trips ->
|
||||
allTrips model
|
||||
|
|
|
@ -40,6 +40,9 @@ type Msg
|
|||
| ClearErrors
|
||||
| ToggleLoginForm
|
||||
| PrintPage
|
||||
| UpdateInviteEmail String
|
||||
| UpdateInviteRole (Maybe Role)
|
||||
| ReceiveTodaysDate Date.Date
|
||||
-- SPA
|
||||
| LinkClicked Browser.UrlRequest
|
||||
| UrlChanged Url.Url
|
||||
|
@ -52,6 +55,7 @@ type Msg
|
|||
| AttemptDeleteAccount String
|
||||
| AttemptCreateTrip Date.Date Date.Date
|
||||
| AttemptDeleteTrip Trip
|
||||
| AttemptInviteUser Role
|
||||
-- Inbound network
|
||||
| GotAccounts (WebData (List Account))
|
||||
| GotTrips (WebData (List Trip))
|
||||
|
@ -61,6 +65,7 @@ type Msg
|
|||
| GotDeleteAccount (Result Http.Error String)
|
||||
| GotCreateTrip (Result Http.Error ())
|
||||
| GotDeleteTrip (Result Http.Error ())
|
||||
| GotInviteUser (Result Http.Error ())
|
||||
|
||||
|
||||
type Route
|
||||
|
@ -121,6 +126,7 @@ type alias Model =
|
|||
, url : Url.Url
|
||||
, key : Nav.Key
|
||||
, session : Maybe Session
|
||||
, todaysDate : Maybe Date.Date
|
||||
, username : String
|
||||
, email : String
|
||||
, password : String
|
||||
|
@ -135,12 +141,16 @@ type alias Model =
|
|||
, trips : WebData (List Trip)
|
||||
, adminTab : AdminTab
|
||||
, loginTab : LoginTab
|
||||
, inviteEmail : String
|
||||
, inviteRole : Maybe Role
|
||||
, inviteResponseStatus : WebData ()
|
||||
, loginError : Maybe Http.Error
|
||||
, logoutError : Maybe Http.Error
|
||||
, signUpError : Maybe Http.Error
|
||||
, deleteUserError : Maybe Http.Error
|
||||
, createTripError : Maybe Http.Error
|
||||
, deleteTripError : Maybe Http.Error
|
||||
, inviteUserError : Maybe Http.Error
|
||||
}
|
||||
|
||||
|
||||
|
@ -151,6 +161,7 @@ allErrors model =
|
|||
, ( model.signUpError, "Error attempting to create your account" )
|
||||
, ( model.deleteUserError, "Error attempting to delete a user" )
|
||||
, ( model.createTripError, "Error attempting to create a trip" )
|
||||
, ( model.inviteUserError, "Error attempting to invite a user" )
|
||||
]
|
||||
|
||||
|
||||
|
@ -178,6 +189,19 @@ endpoint =
|
|||
UrlBuilder.crossOrigin Shared.serverOrigin
|
||||
|
||||
|
||||
encodeRole : Role -> JE.Value
|
||||
encodeRole x =
|
||||
case x of
|
||||
User ->
|
||||
JE.string "user"
|
||||
|
||||
Manager ->
|
||||
JE.string "manager"
|
||||
|
||||
Admin ->
|
||||
JE.string "admin"
|
||||
|
||||
|
||||
decodeRole : JD.Decoder Role
|
||||
decodeRole =
|
||||
let
|
||||
|
@ -254,6 +278,21 @@ signUp { username, email, password } =
|
|||
}
|
||||
|
||||
|
||||
inviteUser : { email : String, role : Role } -> Cmd Msg
|
||||
inviteUser { email, role } =
|
||||
Utils.postWithCredentials
|
||||
{ url = endpoint [ "invite" ] []
|
||||
, body =
|
||||
Http.jsonBody
|
||||
(JE.object
|
||||
[ ( "email", JE.string email )
|
||||
, ( "role", encodeRole role )
|
||||
]
|
||||
)
|
||||
, expect = Http.expectWhatever GotInviteUser
|
||||
}
|
||||
|
||||
|
||||
createTrip :
|
||||
{ username : String
|
||||
, destination : String
|
||||
|
@ -424,6 +463,7 @@ prod _ url key =
|
|||
, url = url
|
||||
, key = key
|
||||
, session = Nothing
|
||||
, todaysDate = Nothing
|
||||
, username = ""
|
||||
, email = ""
|
||||
, password = ""
|
||||
|
@ -438,16 +478,21 @@ prod _ url key =
|
|||
, endDatePicker = endDatePicker
|
||||
, adminTab = Accounts
|
||||
, loginTab = LoginForm
|
||||
, inviteEmail = ""
|
||||
, inviteRole = Nothing
|
||||
, inviteResponseStatus = RemoteData.NotAsked
|
||||
, loginError = Nothing
|
||||
, logoutError = Nothing
|
||||
, signUpError = Nothing
|
||||
, deleteUserError = Nothing
|
||||
, createTripError = Nothing
|
||||
, deleteTripError = Nothing
|
||||
, inviteUserError = Nothing
|
||||
}
|
||||
, Cmd.batch
|
||||
[ Cmd.map UpdateTripStartDate startDatePickerCmd
|
||||
, Cmd.map UpdateTripEndDate endDatePickerCmd
|
||||
, Date.today |> Task.perform ReceiveTodaysDate
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -632,6 +677,15 @@ update msg model =
|
|||
PrintPage ->
|
||||
( model, printPage () )
|
||||
|
||||
UpdateInviteEmail x ->
|
||||
( { model | inviteEmail = x }, Cmd.none )
|
||||
|
||||
UpdateInviteRole mRole ->
|
||||
( { model | inviteRole = mRole }, Cmd.none )
|
||||
|
||||
ReceiveTodaysDate date ->
|
||||
( { model | todaysDate = Just date }, Cmd.none )
|
||||
|
||||
LinkClicked urlRequest ->
|
||||
case urlRequest of
|
||||
Browser.Internal url ->
|
||||
|
@ -766,6 +820,33 @@ update msg model =
|
|||
, sleepAndClearErrors
|
||||
)
|
||||
|
||||
AttemptInviteUser role ->
|
||||
( { model | inviteResponseStatus = RemoteData.Loading }
|
||||
, inviteUser
|
||||
{ email = model.inviteEmail
|
||||
, role = role
|
||||
}
|
||||
)
|
||||
|
||||
GotInviteUser result ->
|
||||
case result of
|
||||
Ok _ ->
|
||||
( { model
|
||||
| inviteEmail = ""
|
||||
, inviteRole = Nothing
|
||||
, inviteResponseStatus = RemoteData.Success ()
|
||||
}
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Err x ->
|
||||
( { model
|
||||
| inviteUserError = Just x
|
||||
, inviteResponseStatus = RemoteData.Failure x
|
||||
}
|
||||
, sleepAndClearErrors
|
||||
)
|
||||
|
||||
-- POST /accounts
|
||||
AttemptSignUp ->
|
||||
( model
|
||||
|
|
Loading…
Reference in a new issue