Skip to content

Commit

Permalink
Add keyboard shortcuts to modals
Browse files Browse the repository at this point in the history
  • Loading branch information
janslifka committed Jan 23, 2025
1 parent 7ac3ab5 commit 0837a3c
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 64 deletions.
1 change: 1 addition & 0 deletions elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"jinjor/elm-diff": "1.0.6",
"justinmimbs/time-extra": "1.2.0",
"kuon/elm-string-normalize": "1.0.6",
"leojpod/elm-keyboard-shortcut": "1.0.1",
"myrho/elm-round": "1.0.5",
"noahzgordon/elm-color-extra": "1.0.2",
"pablohirafuji/elm-syntax-highlight": "3.6.0",
Expand Down
4 changes: 4 additions & 0 deletions engine-wizard/elm/Wizard/Common/Components/Questionnaire.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,8 @@ viewActionResultModal appState model =
Modal.simple
{ modalContent = modalContent
, visible = Maybe.isJust model.questionnaireActionResult
, enterMsg = Just CloseActionResult
, escMsg = Just CloseActionResult
, dataCy = "questionnaire-action-result"
}

Expand Down Expand Up @@ -2185,6 +2187,8 @@ viewPhaseModal appState model =
[ div [] (List.indexedMap viewPhase phases)
]
]
, enterMsg = Nothing
, escMsg = Just (PhaseModalUpdate False Nothing)
, visible = model.phaseModalOpen
, dataCy = "phase-selection"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,9 +245,18 @@ view appState isKmEditor model =
]
]

( enterMsg, escMsg ) =
if ActionResult.isLoading model.submitting then
( Nothing, Nothing )

else
( Just Save, Just Close )

modalConfig =
{ modalContent = modalContent
, visible = model.isOpen
, enterMsg = enterMsg
, escMsg = escMsg
, dataCy = "file-upload"
}
in
Expand Down
8 changes: 6 additions & 2 deletions engine-wizard/elm/Wizard/Common/Menu/View.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Wizard.Common.Menu.View exposing (view, viewAboutModal, viewLanguagesModal, viewReportIssueModal)

import ActionResult exposing (ActionResult(..))
import ActionResult exposing (ActionResult)
import Dict
import Gettext exposing (gettext)
import Html exposing (Html, a, button, code, div, em, h5, img, li, p, span, table, tbody, td, text, th, thead, tr, ul)
Expand Down Expand Up @@ -785,8 +785,8 @@ viewReportIssueModal appState isOpen =
Modal.confirmConfig (gettext "Report Issue" appState.locale)
|> Modal.confirmConfigContent modalContent
|> Modal.confirmConfigVisible isOpen
|> Modal.confirmConfigActionResult Unset
|> Modal.confirmConfigAction (gettext "OK" appState.locale) (Wizard.Msgs.MenuMsg <| SetReportIssueOpen False)
|> Modal.confirmConfigCancelShortcutMsg (Wizard.Msgs.MenuMsg <| SetReportIssueOpen False)
|> Modal.confirmConfigDataCy "report-issue"
in
Modal.confirm appState modalConfig
Expand Down Expand Up @@ -842,6 +842,8 @@ viewAboutModal appState isOpen recentlyCopied serverBuildInfoActionResult =
modalConfig =
{ modalContent = modalContent
, visible = isOpen
, enterMsg = Just (Wizard.Msgs.MenuMsg (SetAboutOpen False))
, escMsg = Just (Wizard.Msgs.MenuMsg (SetAboutOpen False))
, dataCy = "about"
}
in
Expand Down Expand Up @@ -955,5 +957,7 @@ viewLanguagesModal appState visible =
Modal.simple
{ modalContent = content
, visible = visible
, enterMsg = Nothing
, escMsg = Just (Wizard.Msgs.MenuMsg (Wizard.Common.Menu.Msgs.SetLanguagesOpen False))
, dataCy = "languages"
}
93 changes: 76 additions & 17 deletions engine-wizard/elm/Wizard/Common/View/Modal.elm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module Wizard.Common.View.Modal exposing
, confirmConfigAction
, confirmConfigActionResult
, confirmConfigCancelMsg
, confirmConfigCancelShortcutMsg
, confirmConfigContent
, confirmConfigDangerous
, confirmConfigDataCy
Expand All @@ -25,7 +26,9 @@ import Html exposing (Attribute, Html, button, div, h5, pre, text)
import Html.Attributes exposing (class, classList, disabled)
import Html.Events exposing (onClick)
import Html.Extra as Html
import Maybe.Extra as Maybe
import Shared.Html exposing (emptyNode)
import Shortcut
import Wizard.Common.AppState exposing (AppState)
import Wizard.Common.GuideLinks exposing (GuideLinks)
import Wizard.Common.Html exposing (guideLink)
Expand All @@ -37,6 +40,8 @@ import Wizard.Common.View.FormResult as FormResult
type alias SimpleConfig msg =
{ modalContent : List (Html msg)
, visible : Bool
, enterMsg : Maybe msg
, escMsg : Maybe msg
, dataCy : String
}

Expand All @@ -48,7 +53,19 @@ simple =

simpleWithAttrs : List (Attribute msg) -> SimpleConfig msg -> Html msg
simpleWithAttrs attributes cfg =
div ([ class "modal modal-cover", classList [ ( "visible", cfg.visible ) ] ] ++ attributes)
let
shortcuts =
if cfg.visible then
Maybe.values
[ Maybe.map (Shortcut.simpleShortcut Shortcut.Enter) cfg.enterMsg
, Maybe.map (Shortcut.simpleShortcut Shortcut.Escape) cfg.escMsg
]

else
[]
in
Shortcut.shortcutElement shortcuts
([ class "modal modal-cover", classList [ ( "visible", cfg.visible ) ] ] ++ attributes)
[ div [ class "modal-dialog" ]
[ div [ class "modal-content", dataCy ("modal_" ++ cfg.dataCy) ]
cfg.modalContent
Expand All @@ -67,6 +84,7 @@ type alias ConfirmConfigData msg =
, actionResult : ActionResult String
, action : Maybe ( String, msg )
, cancelMsg : Maybe msg
, cancelShortcutMsg : Maybe msg
, dangerous : Bool
, extraClass : Maybe String
, guideLink : Maybe (GuideLinks -> String)
Expand All @@ -83,6 +101,7 @@ confirmConfig title =
, actionResult = ActionResult.Unset
, action = Nothing
, cancelMsg = Nothing
, cancelShortcutMsg = Nothing
, dangerous = False
, extraClass = Nothing
, guideLink = Nothing
Expand Down Expand Up @@ -120,6 +139,11 @@ confirmConfigMbCancelMsg cancelMsg (ConfirmConfig data) =
ConfirmConfig { data | cancelMsg = cancelMsg }


confirmConfigCancelShortcutMsg : msg -> ConfirmConfig msg -> ConfirmConfig msg
confirmConfigCancelShortcutMsg cancelShortcutMsg (ConfirmConfig data) =
ConfirmConfig { data | cancelShortcutMsg = Just cancelShortcutMsg }


confirmConfigDangerous : Bool -> ConfirmConfig msg -> ConfirmConfig msg
confirmConfigDangerous dangerous (ConfirmConfig data) =
ConfirmConfig { data | dangerous = dangerous }
Expand All @@ -146,32 +170,61 @@ confirm appState (ConfirmConfig data) =
content =
FormResult.view appState data.actionResult :: data.modalContent

actionButton =
actionsDisabled =
not data.visible || ActionResult.isLoading data.actionResult

wrapShortcut shortcut =
if actionsDisabled then
Nothing

else
Just shortcut

( actionButton, actionShortcut ) =
case data.action of
Just ( actionName, actionMsg ) ->
ActionButton.buttonWithAttrs appState <|
ActionButton.ButtonWithAttrsConfig actionName data.actionResult actionMsg data.dangerous [ dataCy "modal_action-button" ]
let
btn =
ActionButton.buttonWithAttrs appState <|
ActionButton.ButtonWithAttrsConfig actionName data.actionResult actionMsg data.dangerous [ dataCy "modal_action-button" ]

shortcut =
wrapShortcut (Shortcut.simpleShortcut Shortcut.Enter actionMsg)
in
( btn, shortcut )

Nothing ->
emptyNode
( emptyNode, Nothing )

cancelButton =
( cancelButton, cancelShortcut ) =
case data.cancelMsg of
Just cancelMsg ->
let
cancelDisabled =
ActionResult.isLoading data.actionResult
btn =
button
[ onClick cancelMsg
, disabled actionsDisabled
, class "btn btn-secondary"
, dataCy "modal_cancel-button"
]
[ text (gettext "Cancel" appState.locale) ]

shortcut =
wrapShortcut (Shortcut.simpleShortcut Shortcut.Escape cancelMsg)
in
button
[ onClick cancelMsg
, disabled cancelDisabled
, class "btn btn-secondary"
, dataCy "modal_cancel-button"
]
[ text (gettext "Cancel" appState.locale) ]
( btn, shortcut )

Nothing ->
emptyNode
case data.cancelShortcutMsg of
Just cancelShortcutMsg ->
let
shortcut =
wrapShortcut (Shortcut.simpleShortcut Shortcut.Escape cancelShortcutMsg)
in
( emptyNode, shortcut )

Nothing ->
( emptyNode, Nothing )

mbGuideLink =
case data.guideLink of
Expand All @@ -180,8 +233,12 @@ confirm appState (ConfirmConfig data) =

Nothing ->
Html.nothing

shortcuts =
Maybe.values [ actionShortcut, cancelShortcut ]
in
div [ class "modal modal-cover", class (Maybe.withDefault "" data.extraClass), classList [ ( "visible", data.visible ) ] ]
Shortcut.shortcutElement shortcuts
[ class "modal modal-cover", class (Maybe.withDefault "" data.extraClass), classList [ ( "visible", data.visible ) ] ]
[ div [ class "modal-dialog" ]
[ div [ class "modal-content", dataCy ("modal_" ++ Maybe.withDefault "confirm" data.dataCy) ]
[ div [ class "modal-header" ]
Expand Down Expand Up @@ -227,6 +284,8 @@ error appState cfg =
modalConfig =
{ modalContent = modalContent
, visible = cfg.visible
, enterMsg = Just cfg.actionMsg
, escMsg = Just cfg.actionMsg
, dataCy = cfg.dataCy
}
in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,8 @@ viewAddFolderModal appState model =
Modal.simple
{ modalContent = modalContent
, visible = model.addFolderModalOpen
, enterMsg = Just AddFolderModalSubmit
, escMsg = Just (SetAddFolderModalOpen False)
, dataCy = "add-file-modal"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,18 @@ view appState model =
]
]

( enterMsg, escMsg ) =
if ActionResult.isLoading actionResult then
( Nothing, Nothing )

else
( Just Upload, Just (SetOpen False) )

modalConfig =
{ modalContent = content
, visible = model.open
, enterMsg = enterMsg
, escMsg = escMsg
, dataCy = "logo-upload"
}
in
Expand Down
9 changes: 9 additions & 0 deletions engine-wizard/elm/Wizard/Documents/Index/View.elm
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,18 @@ submitModal appState model =
]
]

( enterMsg, escMsg ) =
if ActionResult.isLoading model.submittingDocument then
( Nothing, Nothing )

else
( Just SubmitDocument, Just (ShowHideSubmitDocument Nothing) )

modalConfig =
{ modalContent = content
, visible = visible
, enterMsg = enterMsg
, escMsg = escMsg
, dataCy = "document-submit"
}
in
Expand Down
Loading

0 comments on commit 0837a3c

Please sign in to comment.