Skip to content

Commit

Permalink
Add maintenance mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Janiczek committed Nov 10, 2024
1 parent a6e5497 commit 9d5f1a6
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 16 deletions.
13 changes: 12 additions & 1 deletion src/Admin.elm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ backendModelCodec randomSeed =
(Queue.codec (Codec.triple Codec.string Codec.string toBackendMsgCodec))
|> Codec.field "randomSeed" .randomSeed (Codec.succeed randomSeed)
|> Codec.field "playerDataCache" .playerDataCache (Dict.ExtraExtra.codec Codec.string Codec.int)
|> Codec.field "isInMaintenance" .isInMaintenance Codec.bool
|> Codec.buildObject


Expand Down Expand Up @@ -173,7 +174,7 @@ toBackendMsgCodec =
adminToBackendCodec : Codec AdminToBackend
adminToBackendCodec =
Codec.custom
(\exportJsonEncoder importJsonEncoder createNewWorldEncoder changeWorldSpeedEncoder value ->
(\exportJsonEncoder importJsonEncoder createNewWorldEncoder changeWorldSpeedEncoder switchMaintenanceEncoder value ->
case value of
ExportJson ->
exportJsonEncoder
Expand All @@ -186,6 +187,9 @@ adminToBackendCodec =

ChangeWorldSpeed arg0 ->
changeWorldSpeedEncoder arg0

SwitchMaintenance arg0 ->
switchMaintenanceEncoder arg0
)
|> Codec.variant0 "ExportJson" ExportJson
|> Codec.variant1 "ImportJson" ImportJson Codec.string
Expand All @@ -198,4 +202,11 @@ adminToBackendCodec =
|> Codec.field "fast" .fast Codec.bool
|> Codec.buildObject
)
|> Codec.variant1
"SwitchMaintenance"
SwitchMaintenance
(Codec.object (\now -> { now = now })
|> Codec.field "now" .now Codec.bool
|> Codec.buildObject
)
|> Codec.buildCustom
28 changes: 25 additions & 3 deletions src/Backend.elm
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ init =
, lastTenToBackendMsgs = Queue.empty
, randomSeed = Random.initialSeed 0
, playerDataCache = Dict.empty
, isInMaintenance = False
}
, Task.perform FirstTick Time.now
)
Expand Down Expand Up @@ -306,7 +307,11 @@ update msg model =
getWorlds model
in
( model
, Lamdera.sendToFrontend clientId <| CurrentWorlds worlds
, Lamdera.sendToFrontend clientId <|
CurrentWorlds
{ worlds = worlds
, isInMaintenance = model.isInMaintenance
}
)

Disconnected _ clientId ->
Expand Down Expand Up @@ -1095,14 +1100,22 @@ updateFromFrontend sessionId clientId msg model =
getWorlds model
in
( model
, Lamdera.sendToFrontend clientId <| CurrentWorlds worlds
, Lamdera.sendToFrontend clientId <|
CurrentWorlds
{ worlds = worlds
, isInMaintenance = model.isInMaintenance
}
)

RefreshPlease ->
let
loggedOut () =
( model
, Lamdera.sendToFrontend clientId <| CurrentWorlds <| getWorlds model
, Lamdera.sendToFrontend clientId <|
CurrentWorlds
{ worlds = getWorlds model
, isInMaintenance = model.isInMaintenance
}
)
in
if isAdmin sessionId clientId model then
Expand Down Expand Up @@ -1256,6 +1269,15 @@ updateAdmin clientId msg model =
|> Cmd.with (refreshAdminData newModel)
|> Cmd.andThen (refreshPlayersOnWorld r.world)

SwitchMaintenance r ->
( { model
| isInMaintenance = r.now
, playerDataCache = Dict.empty
, loggedInPlayers = BiDict.empty
}
, Lamdera.broadcast <| MaintenanceModeChanged r
)


refreshPlayersOnWorld : World.Name -> Model -> ( Model, Cmd BackendMsg )
refreshPlayersOnWorld worldName model =
Expand Down
114 changes: 103 additions & 11 deletions src/Frontend.elm
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ init url key =
, loginForm = Auth.init
, worlds = Nothing
, worldData = worldData
, isInMaintenance = False

-- mostly player frontend state
, newChar = NewChar.init
Expand Down Expand Up @@ -652,6 +653,11 @@ update msg ({ loginForm } as model) =
, Lamdera.sendToBackend <| AdminToBackend <| ChangeWorldSpeed r
)

AskToSwitchMaintenance r ->
( model
, Lamdera.sendToBackend <| AdminToBackend <| SwitchMaintenance r
)


resetBarter : Model -> ( Model, Cmd FrontendMsg )
resetBarter model =
Expand Down Expand Up @@ -793,16 +799,54 @@ updateFromBackend msg model =
}
|> update (GoToRoute (Route.loggedOut model.route))

CurrentWorlds worlds ->
CurrentWorlds { worlds, isInMaintenance } ->
( { model
| worlds = Just worlds
, loginForm =
model.loginForm
|> Auth.selectDefaultWorld worlds
, isInMaintenance = isInMaintenance
}
, Cmd.none
)

MaintenanceModeChanged { now } ->
let
default () =
let
auth =
model.loginForm

newAuth =
{ auth | name = "" }
|> Auth.setPlaintextPassword ""
in
( { model
| isInMaintenance = now
, worldData = NotLoggedIn
, loginForm = newAuth
, route = Route.News
}
, Cmd.none
)
in
case model.worldData of
IsAdmin _ ->
( { model | isInMaintenance = now }
, Cmd.none
)

NotLoggedIn ->
( { model | isInMaintenance = now }
, Cmd.none
)

IsPlayer _ ->
default ()

IsPlayerSigningUp ->
default ()

CurrentOtherPlayers otherPlayers ->
( { model
| worldData =
Expand Down Expand Up @@ -943,7 +987,7 @@ view model =
IsAdmin _ ->
[ alertMessageView model.alertMessage
, H.div [ HA.class "flex flex-col gap-4" ]
[ adminLinksView model.route
[ adminLinksView model
, commonLinksView model.route
]
]
Expand Down Expand Up @@ -973,19 +1017,48 @@ view model =
, commonLinksView model.route
]
]

default () =
if Route.isStandalone model.route then
contentView model
:: preload model

else
appView { leftNav = leftNav } model
:: preload model
in
{ title = "NuAshworld " ++ Version.version
, body =
if Route.isStandalone model.route then
contentView model
:: preload model
if model.isInMaintenance then
case model.worldData of
IsAdmin _ ->
default ()

NotLoggedIn ->
default ()

IsPlayer _ ->
[ maintenanceView ]

IsPlayerSigningUp ->
[ maintenanceView ]

else
appView { leftNav = leftNav } model
:: preload model
default ()
}


maintenanceView : Html FrontendMsg
maintenanceView =
H.div
[ HA.class "pt-8 px-10 pb-10 flex items-center justify-center min-h-screen min-w-screen" ]
[ H.div [ HA.class "flex flex-col gap-4" ]
[ H.span [ HA.class "text-lg" ] [ H.text "Under maintenance" ]
, H.span [] [ H.text "NuAshworld is under maintenance right now. Please wait a few minutes, this page will update automatically." ]
]
]


preload : Model -> List (Html FrontendMsg)
preload model =
if model.hoveredGuideNavLink then
Expand Down Expand Up @@ -1035,6 +1108,8 @@ leftNavView leftNav model =
in
H.div [ HA.class "bg-green-800 min-w-[28ch] max-w-[28ch] px-6 pb-10 pt-[26px] flex flex-col gap-10 items-center max-h-screen overflow-hidden fixed z-[2] left-0 top-0 bottom-0" ]
[ logoView model
, H.viewIf model.isInMaintenance <|
H.div [ HA.class "text-yellow" ] [ H.text "Under maintenance" ]
, H.div [ HA.class "flex flex-col items-center gap-6" ]
(leftNav tickFrequency)
]
Expand Down Expand Up @@ -1082,7 +1157,11 @@ contentView model =
in
H.div
[ HA.class "pt-8 px-10 pb-10 flex flex-col items-start min-h-screen"
, HA.class "min-w-[calc(100vw_-_28ch)]"
, if isStandaloneRoute then
HA.class "min-w-screen"

else
HA.class "min-w-[calc(100vw_-_28ch)]"
, HA.classList [ ( "ml-[28ch]", not isStandaloneRoute ) ]
]
(case ( model.route, model.worldData ) of
Expand Down Expand Up @@ -5448,15 +5527,28 @@ loggedInLinksView p currentRoute =
|> H.div []


adminLinksView : Route -> Html FrontendMsg
adminLinksView currentRoute =
adminLinksView : Model -> Html FrontendMsg
adminLinksView model =
[ LinkMsg { label = "Refresh", msg = Refresh, tooltip = Nothing, disabled = False }
, LinkIn { label = "Worlds", route = AdminRoute AdminWorldsList, highlight = HNormal }
, LinkMsg
{ label =
"Maint "
++ (if model.isInMaintenance then
"Off"

else
"On"
)
, msg = AskToSwitchMaintenance { now = not model.isInMaintenance }
, tooltip = Nothing
, disabled = False
}
, LinkMsg { label = "Import", msg = ImportButtonClicked, tooltip = Nothing, disabled = False }
, LinkMsg { label = "Export", msg = AskForExport, tooltip = Nothing, disabled = False }
, LinkMsg { label = "Logout", msg = Logout, tooltip = Nothing, disabled = False }
]
|> List.map (linkView currentRoute)
|> List.map (linkView model.route)
|> H.div []


Expand Down
7 changes: 6 additions & 1 deletion src/Types.elm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type alias FrontendModel =
, loginForm : Auth Plaintext
, worlds : Maybe (List WorldInfo)
, worldData : WorldData
, isInMaintenance : Bool

-- player frontend state:
, alertMessage : Maybe String
Expand Down Expand Up @@ -84,6 +85,7 @@ type alias BackendModel =
, -- We don't want to send the same data to players over and over when
-- Tick-ing. This lets us skip that work.
playerDataCache : Dict ClientId Int
, isInMaintenance : Bool
}


Expand Down Expand Up @@ -149,6 +151,7 @@ type FrontendMsg
| HoveredGuideNavLink
| AskToRefuelCar ItemKind.Kind
| AskToChangeWorldSpeed { world : World.Name, fast : Bool }
| AskToSwitchMaintenance { now : Bool }


type BarterMsg
Expand Down Expand Up @@ -205,6 +208,7 @@ type AdminToBackend
| ImportJson String
| CreateNewWorld String Bool
| ChangeWorldSpeed { world : World.Name, fast : Bool }
| SwitchMaintenance { now : Bool }


type BackendMsg
Expand All @@ -226,10 +230,11 @@ type alias PlayerData_ =
type ToFrontend
= CurrentPlayer PlayerData
| CurrentOtherPlayers (List COtherPlayer)
| CurrentWorlds (List WorldInfo)
| CurrentWorlds { worlds : List WorldInfo, isInMaintenance : Bool }
| CurrentAdmin AdminData
| CurrentAdminLoggedInPlayers (Dict World.Name (List PlayerName))
| CurrentAdminLastTenToBackendMsgs (List ( PlayerName, World.Name, ToBackend ))
| MaintenanceModeChanged { now : Bool }
| YoureLoggedOut (List WorldInfo)
| YourFightResult ( Fight.Info, PlayerData )
| YoureLoggedInSigningUp
Expand Down

0 comments on commit 9d5f1a6

Please sign in to comment.