(null)
val onSubmit = dispatchFunc {
- fire(SavePinCommand(party.id, updatedPin))
+ fire(SavePartyCommand(partyId = party.id, pins = listOf(updatedPin)))
reload()
}
val onRemove = if (!pinList.contains(pin)) {
diff --git a/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfig.kt b/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfig.kt
index af73ffbfc4..0182736887 100644
--- a/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfig.kt
+++ b/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfig.kt
@@ -1,7 +1,8 @@
package com.zegreatrob.coupling.client.components.player
+import com.zegreatrob.coupling.action.party.SavePartyCommand
+import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.client.components.DispatchFunc
import com.zegreatrob.coupling.client.components.Paths.currentPairsPath
@@ -26,7 +27,7 @@ import react.useState
import kotlin.js.Json
external interface PlayerConfigProps : Props
- where P : SavePlayerCommand.Dispatcher, P : DeletePlayerCommand.Dispatcher {
+ where P : SavePartyCommand.Dispatcher, P : DeletePlayerCommand.Dispatcher {
var party: PartyDetails
var boost: Boost?
var player: Player
@@ -51,10 +52,12 @@ val PlayerConfig by nfc> { props ->
)
val onSubmit = dispatchFunc {
fire(
- SavePlayerCommand(
+ SavePartyCommand(
partyId = party.id,
- player = updatedPlayer.copy(
- additionalEmails = updatedPlayer.additionalEmails.filterNot(String::isBlank).toSet(),
+ players = listOf(
+ updatedPlayer.copy(
+ additionalEmails = updatedPlayer.additionalEmails.filterNot(String::isBlank).toSet(),
+ ),
),
),
)
diff --git a/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerList.kt b/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerList.kt
index b796481f02..9fbe86f57f 100644
--- a/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerList.kt
+++ b/client/components/src/jsMain/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerList.kt
@@ -1,7 +1,7 @@
package com.zegreatrob.coupling.client.components.player
import com.zegreatrob.coupling.action.VoidResult
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
+import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.client.components.DispatchFunc
import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.minreact.ReactFunc
@@ -13,7 +13,7 @@ import react.Props
import react.ReactNode
import react.useState
-external interface UpdatingPlayerListProps : Props where D : SavePlayerCommand.Dispatcher {
+external interface UpdatingPlayerListProps : Props where D : SavePartyCommand.Dispatcher {
var players: List
var dispatchFunc: DispatchFunc
var children: (List, DispatchFunc) -> ReactNode
@@ -62,8 +62,8 @@ private class SecretCannon(
) {
val unwrappedAction = action.unwrap()
@Suppress("USELESS_IS_CHECK")
- if (unwrappedAction is SavePlayerCommand && result == VoidResult.Accepted) {
- addPlayer(unwrappedAction.player)
+ if (unwrappedAction is SavePartyCommand && result == VoidResult.Accepted) {
+ unwrappedAction.players.forEach(addPlayer)
}
}
}
diff --git a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/contributor/ContributorMenuTest.kt b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/contributor/ContributorMenuTest.kt
index e35d7f9d04..457c99c143 100644
--- a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/contributor/ContributorMenuTest.kt
+++ b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/contributor/ContributorMenuTest.kt
@@ -1,6 +1,6 @@
package com.zegreatrob.coupling.client.components.contributor
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
+import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.client.components.Paths.playerConfigPath
import com.zegreatrob.coupling.client.components.StubDispatcher
import com.zegreatrob.coupling.client.components.TestRouter
@@ -84,17 +84,21 @@ class ContributorMenuTest {
} verify {
stubDispatcher.receivedActions
.map {
- if (it !is SavePlayerCommand) {
+ if (it !is SavePartyCommand) {
it
} else {
- it.copy(player = it.player.copy(id = PlayerId("generated".toNotBlankString().getOrThrow())))
+ it.copy(
+ players = it.players.map { player ->
+ player.copy(id = PlayerId("generated".toNotBlankString().getOrThrow()))
+ },
+ )
}
}
.assertIsEqualTo(
listOf(
- SavePlayerCommand(
- partyId,
- contributor.copy(id = PlayerId("generated".toNotBlankString().getOrThrow())),
+ SavePartyCommand(
+ partyId = partyId,
+ players = listOf(contributor.copy(id = PlayerId("generated".toNotBlankString().getOrThrow()))),
),
),
)
@@ -122,9 +126,11 @@ class ContributorMenuTest {
stubDispatcher.receivedActions
.assertIsEqualTo(
listOf(
- SavePlayerCommand(
+ SavePartyCommand(
partyId = partyId,
- player = targetPlayer.copy(additionalEmails = targetPlayer.additionalEmails + contributor.email),
+ players = listOf(
+ targetPlayer.copy(additionalEmails = targetPlayer.additionalEmails + contributor.email),
+ ),
),
),
)
diff --git a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/party/PartyConfigTest.kt b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/party/PartyConfigTest.kt
index ac7674d989..81373e5bb3 100644
--- a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/party/PartyConfigTest.kt
+++ b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/party/PartyConfigTest.kt
@@ -115,7 +115,11 @@ class PartyConfigTest {
stubDispatcher.receivedActions
.filterIsInstance()
.first()
- .party.id.value.toString().run {
+ .party
+ ?.id
+ ?.value
+ .toString()
+ .run {
assertIsNotEqualTo("")
assertIsEqualTo(automatedPartyId)
}
diff --git a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/pin/PinConfigEditorTest.kt b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/pin/PinConfigEditorTest.kt
index f5dd7fe5cf..39001c3639 100644
--- a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/pin/PinConfigEditorTest.kt
+++ b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/pin/PinConfigEditorTest.kt
@@ -1,6 +1,6 @@
package com.zegreatrob.coupling.client.components.pin
-import com.zegreatrob.coupling.action.pin.SavePinCommand
+import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.client.components.DispatchFunc
import com.zegreatrob.coupling.client.components.StubDispatcher
import com.zegreatrob.coupling.client.components.assertNotNull
@@ -100,6 +100,8 @@ class PinConfigEditorTest {
act { fireEvent.submit(screen.getByRole("form")) }
} verify {
stubDispatcher.receivedActions
- .assertIsEqualTo(listOf(SavePinCommand(party.id, pin.copy(name = newName, icon = newIcon))))
+ .assertIsEqualTo(
+ listOf(SavePartyCommand(partyId = party.id, pins = listOf(pin.copy(name = newName, icon = newIcon)))),
+ )
}
}
diff --git a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfigTest.kt b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfigTest.kt
index 1166cc30df..1542aace0f 100644
--- a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfigTest.kt
+++ b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/PlayerConfigTest.kt
@@ -1,8 +1,8 @@
package com.zegreatrob.coupling.client.components.player
import com.zegreatrob.coupling.action.VoidResult
+import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.client.components.StubDispatcher
import com.zegreatrob.coupling.client.components.TestRouter
import com.zegreatrob.coupling.client.components.assertNotNull
@@ -71,9 +71,9 @@ class PlayerConfigTest {
} exercise {
act { actor.click(screen.getByRole("button", RoleOptions(name = "Save"))) }
} verify {
- val expectedCommand = SavePlayerCommand(
+ val expectedCommand = SavePartyCommand(
partyId = party.id,
- player = player.copy(avatarType = AvatarType.DicebearAdventurer),
+ players = listOf(player.copy(avatarType = AvatarType.DicebearAdventurer)),
)
stubDispatcher.receivedActions
.assertIsEqualTo(listOf(expectedCommand))
@@ -105,9 +105,9 @@ class PlayerConfigTest {
actor.click(screen.getByRole("button", RoleOptions(name = "Save")))
}
} verify {
- val expectedCommand = SavePlayerCommand(
+ val expectedCommand = SavePartyCommand(
partyId = party.id,
- player = player.copy(avatarType = null),
+ players = listOf(player.copy(avatarType = null)),
)
stubDispatcher.receivedActions
.assertIsEqualTo(listOf(expectedCommand))
@@ -195,9 +195,9 @@ class PlayerConfigTest {
} exercise {
actor.click(screen.getByRole("button", RoleOptions(name = "Save")))
} verify {
- val expectedCommand = SavePlayerCommand(
+ val expectedCommand = SavePartyCommand(
partyId = party.id,
- player = player.copy(additionalEmails = setOf(secondEmail)),
+ players = listOf(player.copy(additionalEmails = setOf(secondEmail))),
)
stubDispatcher.receivedActions
.assertIsEqualTo(listOf(expectedCommand))
@@ -228,7 +228,7 @@ class PlayerConfigTest {
act { actor.click(screen.getByRole("button", RoleOptions(name = "Save"))) }
} verify {
stubDispatcher.receivedActions
- .assertIsEqualTo(listOf(SavePlayerCommand(partyId = party.id, player = player)))
+ .assertIsEqualTo(listOf(SavePartyCommand(partyId = party.id, players = listOf(player))))
}
@Test
@@ -282,7 +282,7 @@ class PlayerConfigTest {
fireEvent.submit(screen.getByRole("form"))
act { altStubDispatcher.onActionReturn(VoidResult.Accepted) }
} verify { action ->
- action.assertIsEqualTo(SavePlayerCommand(party.id, player.copy(name = "nonsense")))
+ action.assertIsEqualTo(SavePartyCommand(partyId = party.id, players = listOf(player.copy(name = "nonsense"))))
reloaderSpy.callCount.assertIsEqualTo(1)
}
diff --git a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerListTest.kt b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerListTest.kt
index abf946e77c..30123e12b7 100644
--- a/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerListTest.kt
+++ b/client/components/src/jsTest/kotlin/com/zegreatrob/coupling/client/components/player/UpdatingPlayerListTest.kt
@@ -1,9 +1,9 @@
package com.zegreatrob.coupling.client.components.player
import com.zegreatrob.coupling.action.VoidResult
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommandWrapper
-import com.zegreatrob.coupling.action.player.fire
+import com.zegreatrob.coupling.action.party.SavePartyCommand
+import com.zegreatrob.coupling.action.party.SavePartyCommandWrapper
+import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.client.components.DispatchFunc
import com.zegreatrob.coupling.client.components.StubDispatcher
import com.zegreatrob.coupling.client.components.stubDispatchFunc
@@ -21,15 +21,15 @@ import kotlin.test.Test
class UpdatingPlayerListTest {
@Test
- fun whenSavePlayerCommandSucceedsWillAddPlayerToList() = asyncSetup(object {
+ fun whenSavePartyCommandSucceedsWillAddPlayerToList() = asyncSetup(object {
val newPlayer = stubPlayer()
val partyId = stubPartyId()
val players = stubPlayers(3)
- val stubCannon = StubCannon(mutableListOf()).apply {
- givenAny(SavePlayerCommandWrapper::class, VoidResult.Accepted)
+ val stubCannon = StubCannon(mutableListOf()).apply {
+ givenAny(SavePartyCommandWrapper::class, VoidResult.Accepted)
}
var lastPlayersCallback: List? = null
- var dispatchFunc: DispatchFunc? = null
+ var dispatchFunc: DispatchFunc? = null
}) {
render {
UpdatingPlayerList(players, dispatchFunc = stubDispatchFunc(stubCannon)) { players, dispatcher ->
@@ -39,22 +39,22 @@ class UpdatingPlayerListTest {
}
}
} exercise {
- act { dispatchFunc?.invoke { fire(SavePlayerCommand(partyId, newPlayer)) }() }
+ act { dispatchFunc?.invoke { fire(SavePartyCommand(partyId = partyId, players = listOf(newPlayer))) }() }
} verify {
- stubCannon.receivedActions.contains(SavePlayerCommand(partyId, newPlayer))
+ stubCannon.receivedActions.contains(SavePartyCommand(partyId = partyId, players = listOf(newPlayer)))
lastPlayersCallback.assertIsEqualTo(players + newPlayer)
}
@Test
- fun whenSavePlayerCommandSucceedsWillReplacePlayerInList() = asyncSetup(object {
+ fun whenSavePartyCommandSucceedsWillReplacePlayerInList() = asyncSetup(object {
val targetPlayer = stubPlayer()
val partyId = stubPartyId()
val players = stubPlayers(3)
- val stubCannon = StubCannon(mutableListOf()).apply {
- givenAny(SavePlayerCommandWrapper::class, VoidResult.Accepted)
+ val stubCannon = StubCannon(mutableListOf()).apply {
+ givenAny(SavePartyCommandWrapper::class, VoidResult.Accepted)
}
var lastPlayersCallback: List? = null
- var dispatchFunc: DispatchFunc? = null
+ var dispatchFunc: DispatchFunc? = null
val updatedPlayer = targetPlayer.copy(name = "Bill")
}) {
render {
@@ -68,20 +68,20 @@ class UpdatingPlayerListTest {
}
}
} exercise {
- act { dispatchFunc?.invoke { fire(SavePlayerCommand(partyId, updatedPlayer)) }() }
+ act { dispatchFunc?.invoke { fire(SavePartyCommand(partyId = partyId, players = listOf(updatedPlayer))) }() }
} verify {
- stubCannon.receivedActions.contains(SavePlayerCommand(partyId, updatedPlayer))
+ stubCannon.receivedActions.contains(SavePartyCommand(partyId = partyId, players = listOf(updatedPlayer)))
lastPlayersCallback.assertIsEqualTo(players + updatedPlayer)
}
@Test
- fun whenSavePlayerCommandFailsWillNotAddPlayerToList() = asyncSetup(object {
+ fun whenSavePartyCommandFailsWillNotAddPlayerToList() = asyncSetup(object {
val newPlayer = stubPlayer()
val partyId = stubPartyId()
val players = stubPlayers(3)
val stubDispatcher = StubDispatcher.Channel()
var lastPlayersCallback: List? = null
- var dispatchFunc: DispatchFunc? = null
+ var dispatchFunc: DispatchFunc? = null
}) {
render {
UpdatingPlayerList(players, dispatchFunc = stubDispatcher.func()) { players, dispatcher ->
@@ -92,7 +92,7 @@ class UpdatingPlayerListTest {
}
} exercise {
act {
- dispatchFunc?.invoke { fire(SavePlayerCommand(partyId, newPlayer)) }()
+ dispatchFunc?.invoke { fire(SavePartyCommand(partyId = partyId, players = listOf(newPlayer))) }()
stubDispatcher.onActionReturn(VoidResult.Rejected)
}
} verify {
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionListPageE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionListPageE2ETest.kt
index b26c28ee65..0c63c6b426 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionListPageE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionListPageE2ETest.kt
@@ -4,7 +4,6 @@ import com.zegreatrob.coupling.action.party.SaveContributionCommand
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.pairassignmentdocument.PairingSet
import com.zegreatrob.coupling.stubmodel.stubContributionInput
@@ -27,8 +26,7 @@ class ContributionListPageE2ETest {
val deletedPlayers = listOf(stubPlayer())
val allPlayers = players + deletedPlayers
}) {
- sdk().fire(SavePartyCommand(party))
- allPlayers.forEach { sdk().fire(SavePlayerCommand(party.id, it)) }
+ sdk().fire(SavePartyCommand(partyId = party.id, party = party, players = allPlayers))
deletedPlayers.forEach { sdk().fire(DeletePlayerCommand(party.id, it.id)) }
sdk().fire(
SaveContributionCommand(
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionOverviewPageE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionOverviewPageE2ETest.kt
index 863f6c2bda..c0f9c67908 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionOverviewPageE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionOverviewPageE2ETest.kt
@@ -4,7 +4,6 @@ import com.zegreatrob.coupling.action.party.SaveContributionCommand
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.pairassignmentdocument.PairingSet
import com.zegreatrob.coupling.stubmodel.stubContributionInput
@@ -53,8 +52,7 @@ class ContributionOverviewPageE2ETest {
val deletedPlayers = listOf(stubPlayer())
val allPlayers = players + deletedPlayers
}) {
- sdk().fire(SavePartyCommand(party))
- allPlayers.forEach { sdk().fire(SavePlayerCommand(party.id, it)) }
+ sdk().fire(SavePartyCommand(partyId = party.id, party = party, players = allPlayers))
deletedPlayers.forEach { sdk().fire(DeletePlayerCommand(party.id, it.id)) }
sdk().fire(
SaveContributionCommand(
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionVisualizationPageE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionVisualizationPageE2ETest.kt
index c3d72cbdbc..a32bad5fe4 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionVisualizationPageE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/ContributionVisualizationPageE2ETest.kt
@@ -4,7 +4,6 @@ import com.zegreatrob.coupling.action.party.SaveContributionCommand
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.e2e.test.PartyConfigPage.findByRole
import com.zegreatrob.coupling.model.ContributionId
@@ -36,8 +35,7 @@ class ContributionVisualizationPageE2ETest {
val deletedPlayers = listOf(stubPlayer())
val allPlayers = players + deletedPlayers
}) {
- sdk().fire(SavePartyCommand(party))
- allPlayers.forEach { sdk().fire(SavePlayerCommand(party.id, it)) }
+ sdk().fire(SavePartyCommand(partyId = party.id, party = party, players = allPlayers))
deletedPlayers.forEach { sdk().fire(DeletePlayerCommand(party.id, it.id)) }
sdk().fire(
SaveContributionCommand(
@@ -66,8 +64,7 @@ class ContributionVisualizationPageE2ETest {
suspend fun styleSelector() = findByRole("combobox", RoleOptions(name = "Visualization Style"))
suspend fun styleOptions() = within(styleSelector()).getAllByRole("option", RoleOptions())
}) {
- sdk().fire(SavePartyCommand(party))
- players.forEach { sdk().fire(SavePlayerCommand(party.id, it)) }
+ sdk().fire(SavePartyCommand(partyId = party.id, party = party, players = players))
ContributionVisualizationPage.goTo(party.id)
} exercise {
(0..
@@ -89,8 +86,7 @@ class ContributionVisualizationPageE2ETest {
suspend fun styleOptions() = within(styleSelector()).getAllByRole("option", RoleOptions())
suspend fun playerCard() = findByText(players.first().name)
}) {
- sdk().fire(SavePartyCommand(party))
- players.forEach { sdk().fire(SavePlayerCommand(party.id, it)) }
+ sdk().fire(SavePartyCommand(partyId = party.id, party = party, players = players))
sdk().fire(
SaveContributionCommand(
party.id,
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PairAssignmentsPageE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PairAssignmentsPageE2ETest.kt
index a38419393a..bb7e50652a 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PairAssignmentsPageE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PairAssignmentsPageE2ETest.kt
@@ -4,7 +4,6 @@ import com.zegreatrob.coupling.action.pairassignmentdocument.SavePairAssignments
import com.zegreatrob.coupling.action.pairassignmentdocument.fire
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.e2e.test.AssignedPair.assignedPairCallSigns
import com.zegreatrob.coupling.e2e.test.AssignedPair.assignedPairElements
@@ -41,9 +40,7 @@ class PairAssignmentsPageE2ETest {
companion object {
private suspend fun ActionCannon.save(party: PartyDetails, players: List) = coroutineScope {
- fire(SavePartyCommand(party))
- players.map { SavePlayerCommand(party.id, it) }
- .forEach { fire(it) }
+ fire(SavePartyCommand(partyId = party.id, party = party, players = players))
}
}
@@ -187,7 +184,7 @@ class PairAssignmentsPageE2ETest {
sdk.await().apply {
fire(SavePartyCommand(party))
coroutineScope {
- launch { players.forEach { fire(SavePlayerCommand(party.id, it)) } }
+ launch { fire(SavePartyCommand(partyId = party.id, party = party, players = players)) }
launch { sdk.await().fire(SavePairAssignmentsCommand(party.id, pairingSet)) }
}
}
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PinConfigE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PinConfigE2ETest.kt
index 64f49f02bc..ba67a8511f 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PinConfigE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PinConfigE2ETest.kt
@@ -2,7 +2,6 @@ package com.zegreatrob.coupling.e2e.test
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.pin.SavePinCommand
import com.zegreatrob.coupling.action.pin.fire
import com.zegreatrob.coupling.e2e.test.ConfigForm.retireButton
import com.zegreatrob.coupling.e2e.test.ConfigForm.saveButton
@@ -101,7 +100,7 @@ class PinConfigE2ETest {
val pin = randomPin()
}.attachParty(),
) {
- sdk.fire(SavePinCommand(party.id, pin))
+ sdk.fire(SavePartyCommand(partyId = party.id, pins = listOf(pin)))
} exercise {
PinConfigPage.goTo(party.id, pin.id)
} verify {
@@ -119,7 +118,7 @@ class PinConfigE2ETest {
val pin = randomPin()
}.attachParty(),
) {
- sdk.fire(SavePinCommand(party.id, pin))
+ sdk.fire(SavePartyCommand(partyId = party.id, pins = listOf(pin)))
PinConfigPage.goTo(party.id, pin.id)
} exercise {
acceptDialogAndGetMessage { retireButton().click() }
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PlayerConfigPageE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PlayerConfigPageE2ETest.kt
index aeb50718ca..ececaa04a9 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PlayerConfigPageE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PlayerConfigPageE2ETest.kt
@@ -5,7 +5,6 @@ package com.zegreatrob.coupling.e2e.test
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.e2e.gql.PartyPlayerListQuery
import com.zegreatrob.coupling.e2e.test.ConfigForm.retireButton
@@ -37,8 +36,7 @@ class PlayerConfigPageE2ETest {
val party = buildParty()
val player = buildPlayer()
sdk.await().apply {
- fire(SavePartyCommand(party))
- fire(SavePlayerCommand(party.id, player))
+ fire(SavePartyCommand(partyId = party.id, party = party, players = listOf(player)))
}
Triple(player, party, sdk.await())
})
@@ -207,8 +205,7 @@ class PlayerConfigPageE2ETest {
val page = PlayerConfigPage
}) {
sdk.await().apply {
- fire(SavePartyCommand(party))
- players.forEach { player -> fire(SavePlayerCommand(party.id, player)) }
+ fire(SavePartyCommand(partyId = party.id, party = party, players = players))
}
PlayerConfigPage.goTo(party.id, players[0].id)
} exercise {
@@ -332,8 +329,7 @@ class PlayerConfigPageE2ETest {
val party = stubPartyDetails()
val player = stubPlayer()
}) {
- sdk().fire(SavePartyCommand(party))
- sdk().fire(SavePlayerCommand(party.id, player))
+ sdk().fire(SavePartyCommand(partyId = party.id, party = party, players = listOf(player)))
sdk().fire(DeletePlayerCommand(party.id, player.id))
} exercise {
PlayerConfigPage.goTo(party.id, player.id)
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PrepareToSpinPageE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PrepareToSpinPageE2ETest.kt
index d584f464eb..e4e4738b16 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PrepareToSpinPageE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/PrepareToSpinPageE2ETest.kt
@@ -2,10 +2,6 @@ package com.zegreatrob.coupling.e2e.test
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.pin.SavePinCommand
-import com.zegreatrob.coupling.action.pin.fire
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.e2e.test.AssignedPair.assignedPairElements
import com.zegreatrob.coupling.e2e.test.CouplingLogin.sdk
import com.zegreatrob.coupling.e2e.test.CurrentPairAssignmentsPanel.getSaveButton
@@ -35,9 +31,7 @@ class PrepareToSpinPageE2ETest {
val players = (1..5).map(Companion::buildPlayer)
val pin = Pin(PinId.new(), name = "e2e-pin")
val sdk = sdk.await().apply {
- fire(SavePartyCommand(party))
- players.forEach { fire(SavePlayerCommand(party.id, it)) }
- sdk.await().fire(SavePinCommand(party.id, pin))
+ fire(SavePartyCommand(partyId = party.id, party = party, players = players, pins = listOf(pin)))
}
FullPartyData(players, listOf(pin), party, sdk)
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/RetiredPlayersPageE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/RetiredPlayersPageE2ETest.kt
index ee3bef54eb..1438060b50 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/RetiredPlayersPageE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/RetiredPlayersPageE2ETest.kt
@@ -3,7 +3,6 @@ package com.zegreatrob.coupling.e2e.test
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.e2e.test.PartyCard.element
import com.zegreatrob.coupling.model.party.PartyDetails
@@ -45,8 +44,7 @@ class RetiredPlayersPageE2ETest {
val notDeletedPlayer = players[2]
val retiredPlayers = players - notDeletedPlayer
}) {
- sdk.fire(SavePartyCommand(party))
- players.forEach { sdk.fire(SavePlayerCommand(party.id, it)) }
+ sdk.fire(SavePartyCommand(partyId = party.id, party = party, players = players))
delete(retiredPlayers, sdk, party)
} exercise {
RetiredPlayersPage.goTo(party.id)
diff --git a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/StatisticsE2ETest.kt b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/StatisticsE2ETest.kt
index 15b0e5a873..0a181e6855 100644
--- a/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/StatisticsE2ETest.kt
+++ b/e2e/src/jsE2eTest/kotlin/com/zegreatrob/coupling/e2e/test/StatisticsE2ETest.kt
@@ -3,7 +3,6 @@ package com.zegreatrob.coupling.e2e.test
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.e2e.test.PartyCard.element
import com.zegreatrob.coupling.model.party.PartyDetails
@@ -26,8 +25,7 @@ class StatisticsE2ETest {
}
.take(6).toList()
}) {
- sdk.fire(SavePartyCommand(party))
- players.forEach { player -> sdk.fire(SavePlayerCommand(party.id, player)) }
+ sdk.fire(SavePartyCommand(partyId = party.id, party = party, players = players))
} exercise {
StatisticsPage.goTo(party.id)
} verify {
@@ -49,8 +47,7 @@ class StatisticsE2ETest {
}
.take(2).toList()
}) {
- sdk.fire(SavePartyCommand(party))
- players.forEach { player -> sdk.fire(SavePlayerCommand(party.id, player)) }
+ sdk.fire(SavePartyCommand(partyId = party.id, party = party, players = players))
sdk.fire(DeletePlayerCommand(party.id, players[0].id))
} exercise {
StatisticsPage.goTo(party.id)
diff --git a/libraries/action/src/commonMain/kotlin/com/zegreatrob/coupling/action/party/SavePartyCommand.kt b/libraries/action/src/commonMain/kotlin/com/zegreatrob/coupling/action/party/SavePartyCommand.kt
index 3f1ea4dddc..9f6fd9e0fe 100644
--- a/libraries/action/src/commonMain/kotlin/com/zegreatrob/coupling/action/party/SavePartyCommand.kt
+++ b/libraries/action/src/commonMain/kotlin/com/zegreatrob/coupling/action/party/SavePartyCommand.kt
@@ -2,10 +2,20 @@ package com.zegreatrob.coupling.action.party
import com.zegreatrob.coupling.action.VoidResult
import com.zegreatrob.coupling.model.party.PartyDetails
+import com.zegreatrob.coupling.model.party.PartyId
+import com.zegreatrob.coupling.model.pin.Pin
+import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.testmints.action.annotation.ActionMint
@ActionMint
-data class SavePartyCommand(val party: PartyDetails) {
+data class SavePartyCommand(
+ val partyId: PartyId,
+ val party: PartyDetails? = null,
+ val players: List = emptyList(),
+ val pins: List = emptyList(),
+) {
+ constructor(party: PartyDetails) : this(party.id, party)
+
fun interface Dispatcher {
suspend fun perform(command: SavePartyCommand): VoidResult
}
diff --git a/libraries/json/build.gradle.kts b/libraries/json/build.gradle.kts
index 39920bd6df..e892df3433 100644
--- a/libraries/json/build.gradle.kts
+++ b/libraries/json/build.gradle.kts
@@ -27,6 +27,7 @@ kotlin {
dependencies {
commonMainApi(project(":libraries:model"))
+ commonMainImplementation(project(":libraries:action"))
commonMainImplementation("io.ktor:ktor-client-content-negotiation")
commonMainImplementation("io.ktor:ktor-client-core")
commonMainImplementation("io.ktor:ktor-client-logging")
diff --git a/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PartyDetailsMapper.kt b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PartyDetailsMapper.kt
index fa91fc43ed..edc7609e25 100644
--- a/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PartyDetailsMapper.kt
+++ b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PartyDetailsMapper.kt
@@ -2,12 +2,13 @@ package com.zegreatrob.coupling.json
import com.zegreatrob.coupling.model.party.PairingRule
import com.zegreatrob.coupling.model.party.PartyDetails
+import com.zegreatrob.coupling.model.party.PartyId
import com.zegreatrob.coupling.model.party.defaultParty
import kotlinx.serialization.Serializable
import org.kotools.types.ExperimentalKotoolsTypesApi
@OptIn(ExperimentalKotoolsTypesApi::class)
-fun GqlSavePartyInput.toModel() = PartyDetails(
+fun GqlSavePartyDetailsInput.toModel(partyId: PartyId) = PartyDetails(
id = partyId,
pairingRule = PairingRule.fromValue(pairingRule),
badgesEnabled = badgesEnabled ?: defaultParty.badgesEnabled,
diff --git a/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PinDetailsMapper.kt b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PinDetailsMapper.kt
index 4b09b957fe..b04c6a537c 100644
--- a/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PinDetailsMapper.kt
+++ b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PinDetailsMapper.kt
@@ -27,3 +27,15 @@ fun GqlPin.toModel(): Record> = Record(
isDeleted = isDeleted,
timestamp = timestamp,
)
+
+fun GqlSavePinInput.toModel() = Pin(
+ id = pinId,
+ name = name,
+ icon = icon,
+)
+
+fun GqlSavePartyPinInput.toModel() = Pin(
+ id = pinId,
+ name = name,
+ icon = icon,
+)
diff --git a/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PlayerDetailsMapper.kt b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PlayerDetailsMapper.kt
index a7f6e9a21f..cc06e6c0ed 100644
--- a/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PlayerDetailsMapper.kt
+++ b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/PlayerDetailsMapper.kt
@@ -35,6 +35,19 @@ fun GqlSavePlayerInput.toModel(): Player = Player(
additionalEmails = unvalidatedEmails.toSet(),
)
+@OptIn(ExperimentalKotoolsTypesApi::class)
+fun GqlSavePartyPlayerInput.toModel(): Player = Player(
+ id = playerId,
+ badge = badge.toModel(),
+ name = name,
+ email = email,
+ callSignAdjective = callSignAdjective,
+ callSignNoun = callSignNoun,
+ imageURL = imageURL,
+ avatarType = avatarType?.let(AvatarType::valueOf),
+ additionalEmails = unvalidatedEmails.toSet(),
+)
+
@OptIn(ExperimentalKotoolsTypesApi::class)
fun GqlPlayer.toModel(): PartyRecord = PartyRecord(
partyId.with(
diff --git a/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/SavePartyInputMapper.kt b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/SavePartyInputMapper.kt
new file mode 100644
index 0000000000..c80fe510e3
--- /dev/null
+++ b/libraries/json/src/commonMain/kotlin/com/zegreatrob/coupling/json/SavePartyInputMapper.kt
@@ -0,0 +1,10 @@
+package com.zegreatrob.coupling.json
+
+import com.zegreatrob.coupling.action.party.SavePartyCommand
+
+fun GqlSavePartyInput.toCommand() = SavePartyCommand(
+ partyId = partyId,
+ party = party?.toModel(partyId),
+ players = players?.items?.map { it.toModel() }.orEmpty(),
+ pins = pins?.items?.map { it.toModel() }.orEmpty(),
+)
diff --git a/notes/save-party-plan.md b/notes/save-party-plan.md
new file mode 100644
index 0000000000..89cc3a5c21
--- /dev/null
+++ b/notes/save-party-plan.md
@@ -0,0 +1,79 @@
+# SaveParty Consolidation + Test Perf Work Plan
+
+## Ultimate Goal
+Unify all save behavior (party, players, pins) through **SaveParty** so tests and app use the same API path, keep implicit upsert, require `party` only for new party creation, and update tests to match without changing expectations. Then run tests and measure any performance delta (including seed command impact). Keep CDN/config-cache changes isolated on their own branch.
+
+## Current Status (As Of 2026-03-03)
+
+### Completed
+1. **Branch split done**
+ - Branch `cdn-config-cache` created with commit `a4cd77482` containing only:
+ - `client/build.gradle.kts`: disable config cache for Vite tasks; validate non-empty `cdn.json` before Vite.
+ - `master` contains only SaveParty refactor work.
+
+2. **Schema + core SaveParty refactor done**
+ - `SavePartyInput` now supports sections: `party`, `players`, `pins`.
+ - `SavePartyCommand` signature expanded: `(partyId, party?, players, pins)`.
+ - Seed mutation removed (schema + server + sdk).
+ - Server SaveParty now saves optional `party` and updates players/pins via repositories.
+ - SaveParty requires `party` only for new party creation; implicit upsert only.
+
+3. **Mapping/SDK/resolver updates done**
+ - New `SavePartyInputMapper` and input DTOs.
+ - Resolver uses new mapper.
+ - SDK SaveParty dispatcher now builds new input shape.
+
+4. **Client runtime uses SaveParty for player/pin saves**
+ - PlayerConfig, UpdatingPlayerList, ContributorMenu, Contribution popups, PinConfig updated to SaveParty.
+
+5. **Many tests updated to SaveParty**
+ - e2e tests updated already (per prior summary).
+ - client component tests updated to SaveParty.
+ - sdk commonTest updated to SaveParty (players/pins).
+
+### Still Pending / Verify
+1. **Run tests**
+ - ✅ `./gradlew test --no-configuration-cache` succeeded on 2026-03-05 after disabling `:testDistributionWebSocketCheck` when no server property is set.
+
+2. **Remove/adjust legacy SavePlayer/SavePin if desired**
+ - Current code keeps SavePlayer/SavePin actions/resolvers/dispatchers for compatibility. Decide whether to deprecate or keep. Tests now use SaveParty.
+
+3. **Regenerate GraphQL code if needed**
+ - If build fails on generated types, run the appropriate Apollo/Gradle tasks.
+
+4. **Measure performance delta**
+ - After tests pass, re-run e2e/perf and compare with prior baseline:
+ - Previous seed mutation delta: 162.779s vs 168.486s (~5.7s faster without seed) from earlier run. Re-measure after new SaveParty path.
+ - ✅ `./gradlew :e2e:e2eRun --no-configuration-cache --rerun-tasks` completed on 2026-03-05 (total build time 3m 48s).
+
+## Work Log (Edits Already Made)
+
+### Key Files Changed
+- Schema: `server/src/jsMain/resources/schema.graphqls`
+- SaveParty model: `libraries/action/src/commonMain/kotlin/.../SavePartyCommand.kt`
+- Server SaveParty dispatcher: `server/actionz/src/jsMain/kotlin/.../ServerSavePartyCommandDispatcher.kt`
+- Resolver: `server/src/jsMain/kotlin/.../SavePartyResolver.kt`
+- SDK: `sdk/src/commonMain/kotlin/.../SdkSavePartyCommandDispatcher.kt`
+- JSON mappers: `libraries/json/.../SavePartyInputMapper.kt`, plus player/pin/party mappers.
+- Client components: PlayerConfig, UpdatingPlayerList, ContributorMenu, Contribution popups, PinConfig.
+- Tests: client component tests; sdk commonTests; e2e tests.
+
+### Tests Updated To SaveParty
+- Client: `UpdatingPlayerListTest`, `PlayerConfigTest`, `PinConfigEditorTest`, `ContributorMenuTest`.
+- SDK: `SdkPlayerTest`, `SdkPinTest`, `SdkPartyTest`, `SdkUserTest`, `SpinTest`, `RequestCombineEndpointTest`, `SdkPairsRecentTimesTest`, `SavePartyState`.
+
+### Known Build Failure
+- Running `./gradlew test --no-configuration-cache` fails at `:testDistributionWebSocketCheck` with:
+ - "Cannot query the value of task ':testDistributionWebSocketCheck' property 'server' because it has no value available."
+ - ✅ Fixed locally by skipping the task when no test distribution server property is set.
+
+## Next Steps (Recommended Order)
+1. Fix/disable Develocity test distribution WebSocket check for local runs.
+2. Re-run `./gradlew test --no-configuration-cache`.
+3. Fix any remaining test failures.
+4. Run e2e/perf measurement and compare results.
+
+## Notes
+- User preference: keep **implicit upsert**; require `party` only for new party creation.
+- User preference: keep API usage as close to app as possible; tests should be updated to new SaveParty path rather than changing expected behavior.
+- Avoid config cache for Vite tasks (done in separate branch `cdn-config-cache`).
diff --git a/sdk/src/commonMain/graphql/savePin.graphql b/sdk/src/commonMain/graphql/savePin.graphql
deleted file mode 100644
index cd6d33c609..0000000000
--- a/sdk/src/commonMain/graphql/savePin.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-mutation savePin($input: SavePinInput!) {
- savePin(input: $input)
-}
diff --git a/sdk/src/commonMain/graphql/savePlayer.graphql b/sdk/src/commonMain/graphql/savePlayer.graphql
deleted file mode 100644
index 5ebacceda9..0000000000
--- a/sdk/src/commonMain/graphql/savePlayer.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-mutation savePlayer($input: SavePlayerInput!) {
- savePlayer(input: $input)
-}
diff --git a/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePartyCommandDispatcher.kt b/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePartyCommandDispatcher.kt
index ec12a2a68e..a7350f2534 100644
--- a/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePartyCommandDispatcher.kt
+++ b/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePartyCommandDispatcher.kt
@@ -5,21 +5,26 @@ import com.zegreatrob.coupling.action.VoidResult
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.model.party.PairingRule
import com.zegreatrob.coupling.model.party.PartyDetails
+import com.zegreatrob.coupling.model.pin.Pin
+import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.coupling.sdk.gql.GqlTrait
import com.zegreatrob.coupling.sdk.schema.SavePartyMutation
import com.zegreatrob.coupling.sdk.schema.type.SavePartyInput
+import com.zegreatrob.coupling.sdk.schema.type.SavePartyPinInput
+import com.zegreatrob.coupling.sdk.schema.type.SavePartyPinsInput
+import com.zegreatrob.coupling.sdk.schema.type.SavePartyPlayerInput
+import com.zegreatrob.coupling.sdk.schema.type.SavePartyPlayersInput
interface SdkSavePartyCommandDispatcher :
SavePartyCommand.Dispatcher,
GqlTrait {
override suspend fun perform(command: SavePartyCommand): VoidResult {
- SavePartyMutation(command.party.savePartyInput()).execute()
+ SavePartyMutation(command.savePartyInput()).execute()
return VoidResult.Accepted
}
}
-private fun PartyDetails.savePartyInput() = SavePartyInput(
- partyId = id,
+internal fun PartyDetails.savePartyDetailsInput() = com.zegreatrob.coupling.sdk.schema.type.SavePartyDetailsInput(
name = presentIfNotNull(name),
email = presentIfNotNull(email),
pairingRule = presentIfNotNull(PairingRule.toValue(pairingRule)),
@@ -30,3 +35,44 @@ private fun PartyDetails.savePartyInput() = SavePartyInput(
animationsEnabled = presentIfNotNull(animationEnabled),
animationSpeed = presentIfNotNull(animationSpeed),
)
+
+internal fun SavePartyCommand.savePartyInput() = SavePartyInput(
+ partyId = partyId,
+ party = presentIfNotNull(party?.savePartyDetailsInput()),
+ players = presentIfNotNull(
+ if (players.isEmpty()) {
+ null
+ } else {
+ SavePartyPlayersInput(
+ items = players.map { it.toSavePartyPlayerInput() },
+ )
+ },
+ ),
+ pins = presentIfNotNull(
+ if (pins.isEmpty()) {
+ null
+ } else {
+ SavePartyPinsInput(
+ items = pins.map { it.toSavePartyPinInput() },
+ )
+ },
+ ),
+)
+
+private fun Player.toSavePartyPlayerInput() = SavePartyPlayerInput(
+ playerId = id,
+ name = name,
+ email = email,
+ badge = badge.toSerializable(),
+ callSignAdjective = callSignAdjective,
+ callSignNoun = callSignNoun,
+ imageURL = presentIfNotNull(imageURL),
+ avatarType = presentIfNotNull(avatarType?.name),
+ unvalidatedEmails = additionalEmails.toList(),
+)
+
+private fun Pin.toSavePartyPinInput() = SavePartyPinInput(
+ pinId = id,
+ icon = icon,
+ name = name,
+)
diff --git a/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePinCommandDispatcher.kt b/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePinCommandDispatcher.kt
index 4b27518016..30e736bfe3 100644
--- a/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePinCommandDispatcher.kt
+++ b/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePinCommandDispatcher.kt
@@ -1,27 +1,21 @@
package com.zegreatrob.coupling.sdk
import com.zegreatrob.coupling.action.VoidResult
+import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.pin.SavePinCommand
-import com.zegreatrob.coupling.model.party.PartyElement
-import com.zegreatrob.coupling.model.party.with
-import com.zegreatrob.coupling.model.pin.Pin
import com.zegreatrob.coupling.sdk.gql.GqlTrait
-import com.zegreatrob.coupling.sdk.schema.SavePinMutation
-import com.zegreatrob.coupling.sdk.schema.type.SavePinInput
+import com.zegreatrob.coupling.sdk.schema.SavePartyMutation
interface SdkSavePinCommandDispatcher :
SavePinCommand.Dispatcher,
GqlTrait {
override suspend fun perform(command: SavePinCommand): VoidResult.Accepted {
- val (partyId, pin) = command
- SavePinMutation(partyId.with(pin).savePinInput()).execute()
+ SavePartyMutation(
+ SavePartyCommand(
+ partyId = command.id,
+ pins = listOf(command.pin),
+ ).savePartyInput(),
+ ).execute()
return VoidResult.Accepted
}
}
-
-private fun PartyElement.savePinInput() = SavePinInput(
- partyId = partyId,
- pinId = element.id,
- icon = element.icon,
- name = element.name,
-)
diff --git a/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePlayerCommandDispatcher.kt b/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePlayerCommandDispatcher.kt
index 1f8d64077b..d319d926d1 100644
--- a/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePlayerCommandDispatcher.kt
+++ b/sdk/src/commonMain/kotlin/com/zegreatrob/coupling/sdk/SdkSavePlayerCommandDispatcher.kt
@@ -1,33 +1,21 @@
package com.zegreatrob.coupling.sdk
-import com.apollographql.apollo.api.Optional.Companion.presentIfNotNull
import com.zegreatrob.coupling.action.VoidResult
+import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.model.party.PartyElement
-import com.zegreatrob.coupling.model.party.with
-import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.coupling.sdk.gql.GqlTrait
-import com.zegreatrob.coupling.sdk.schema.SavePlayerMutation
-import com.zegreatrob.coupling.sdk.schema.type.SavePlayerInput
+import com.zegreatrob.coupling.sdk.schema.SavePartyMutation
interface SdkSavePlayerCommandDispatcher :
SavePlayerCommand.Dispatcher,
GqlTrait {
- override suspend fun perform(command: SavePlayerCommand) = with(command) {
- SavePlayerMutation(partyId.with(player).input()).execute()
- VoidResult.Accepted
+ override suspend fun perform(command: SavePlayerCommand): VoidResult.Accepted {
+ SavePartyMutation(
+ SavePartyCommand(
+ partyId = command.partyId,
+ players = listOf(command.player),
+ ).savePartyInput(),
+ ).execute()
+ return VoidResult.Accepted
}
}
-
-internal fun PartyElement.input() = SavePlayerInput(
- partyId = partyId,
- playerId = element.id,
- name = element.name,
- email = element.email,
- badge = element.badge.toSerializable(),
- callSignAdjective = element.callSignAdjective,
- callSignNoun = element.callSignNoun,
- imageURL = presentIfNotNull(element.imageURL),
- avatarType = presentIfNotNull(element.avatarType?.name),
- unvalidatedEmails = element.additionalEmails.toList(),
-)
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/RequestCombineEndpointTest.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/RequestCombineEndpointTest.kt
index 59aa49279f..2697793dc3 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/RequestCombineEndpointTest.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/RequestCombineEndpointTest.kt
@@ -2,10 +2,6 @@ package com.zegreatrob.coupling.sdk
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.pin.SavePinCommand
-import com.zegreatrob.coupling.action.pin.fire
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.party.PartyDetails
import com.zegreatrob.coupling.model.party.PartyId
import com.zegreatrob.coupling.model.pin.Pin
@@ -40,8 +36,8 @@ class RequestCombineEndpointTest {
}
}) {
sdk.fire(SavePartyCommand(party))
- pinsToSave.forEach { setupScope.launch { sdk.fire(SavePinCommand(party.id, it)) } }
- playersToSave.forEach { setupScope.launch { sdk.fire(SavePlayerCommand(party.id, it)) } }
+ pinsToSave.forEach { setupScope.launch { sdk.fire(SavePartyCommand(partyId = party.id, pins = listOf(it))) } }
+ playersToSave.forEach { setupScope.launch { sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(it))) } }
} exercise {
coroutineScope {
sdk.fire(GqlQuery(PlayersAndPinsQuery(party.id)))
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SavePartyState.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SavePartyState.kt
index e0834ed512..3932f150db 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SavePartyState.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SavePartyState.kt
@@ -4,8 +4,6 @@ import com.zegreatrob.coupling.action.pairassignmentdocument.SavePairAssignments
import com.zegreatrob.coupling.action.pairassignmentdocument.fire
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.pairassignmentdocument.PairingSet
import com.zegreatrob.coupling.model.party.PartyDetails
import com.zegreatrob.coupling.model.player.Player
@@ -19,10 +17,8 @@ suspend fun savePartyState(
) = coroutineScope {
with(sdk()) {
fire(SavePartyCommand(party))
- players.forEach {
- launch {
- fire(SavePlayerCommand(party.id, it))
- }
+ launch {
+ fire(SavePartyCommand(partyId = party.id, players = players))
}
pairAssignmentDocs.forEach {
launch {
@@ -40,7 +36,7 @@ suspend fun savePartyStateWithFixedPlayerOrder(
with(sdk()) {
fire(SavePartyCommand(party))
launch {
- players.forEach { fire(SavePlayerCommand(party.id, it)) }
+ fire(SavePartyCommand(partyId = party.id, players = players))
}
pairAssignmentDocs.forEach {
launch {
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPairsRecentTimesTest.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPairsRecentTimesTest.kt
index a5dace6d5f..9adb1e59a9 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPairsRecentTimesTest.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPairsRecentTimesTest.kt
@@ -5,8 +5,6 @@ import com.zegreatrob.coupling.action.pairassignmentdocument.SavePairAssignments
import com.zegreatrob.coupling.action.pairassignmentdocument.fire
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.pairassignmentdocument.PairingSet
import com.zegreatrob.coupling.model.pairassignmentdocument.PairingSetId
import com.zegreatrob.coupling.model.pairassignmentdocument.pairOf
@@ -150,7 +148,7 @@ class SdkPairsRecentTimesTest {
with(sdk()) {
fire(SavePartyCommand(party))
players.forEach {
- fire(SavePlayerCommand(party.id, it))
+ fire(SavePartyCommand(partyId = party.id, players = listOf(it)))
}
history.forEach {
fire(SavePairAssignmentsCommand(party.id, it))
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPartyTest.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPartyTest.kt
index a1124fa242..a46dc9706b 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPartyTest.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPartyTest.kt
@@ -7,7 +7,6 @@ import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.SaveSlackIntegrationCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.AccessType
import com.zegreatrob.coupling.model.party.PartyDetails
@@ -95,7 +94,7 @@ class SdkPartyTest {
val playerMatchingSdkUser = stubPlayer().copy(email = PRIMARY_AUTHORIZED_USER_EMAIL)
}) {
sdk().fire(SavePartyCommand(party))
- sdk().fire(SavePlayerCommand(party.id, playerMatchingSdkUser))
+ sdk().fire(SavePartyCommand(partyId = party.id, players = listOf(playerMatchingSdkUser)))
} exercise {
sdk().fire(GqlQuery(PartyAccessTypeAndListQuery(party.id)))
} verify { result ->
@@ -130,7 +129,7 @@ class SdkPartyTest {
fun getWillReturnAnyPartyThatHasPlayerWithGivenEmail() = setupWithPlayerMatchingUserTwoSdks {
with(altSdk()) {
fire(SavePartyCommand(party))
- fire(SavePlayerCommand(party.id, playerMatchingSdkUser))
+ fire(SavePartyCommand(partyId = party.id, players = listOf(playerMatchingSdkUser)))
}
} exercise {
sdk().fire(GqlQuery(PartyAccessTypeDetailsListQuery()))
@@ -149,9 +148,9 @@ class SdkPartyTest {
with(altSdk()) {
fire(SavePartyCommand(party))
fire(
- SavePlayerCommand(
- party.id,
- stubPlayer().copy(additionalEmails = setOf(PRIMARY_AUTHORIZED_USER_EMAIL)),
+ SavePartyCommand(
+ partyId = party.id,
+ players = listOf(stubPlayer().copy(additionalEmails = setOf(PRIMARY_AUTHORIZED_USER_EMAIL))),
),
)
}
@@ -168,8 +167,8 @@ class SdkPartyTest {
fun getWillNotReturnPartyIfPlayerHadEmailButThenHadItRemoved() = setupWithPlayerMatchingUserTwoSdks {
with(altSdk()) {
fire(SavePartyCommand(party))
- fire(SavePlayerCommand(party.id, playerMatchingSdkUser))
- fire(SavePlayerCommand(party.id, playerMatchingSdkUser.copy(email = "something else")))
+ fire(SavePartyCommand(partyId = party.id, players = listOf(playerMatchingSdkUser)))
+ fire(SavePartyCommand(partyId = party.id, players = listOf(playerMatchingSdkUser.copy(email = "something else"))))
}
} exercise {
sdk().fire(GqlQuery(PartyAccessTypeDetailsListQuery()))
@@ -183,7 +182,7 @@ class SdkPartyTest {
fun getWillNotReturnPartyIfPlayerHadEmailButPlayerWasRemoved() = setupWithPlayerMatchingUserTwoSdks {
with(altSdk()) {
fire(SavePartyCommand(party))
- fire(SavePlayerCommand(party.id, playerMatchingSdkUser))
+ fire(SavePartyCommand(partyId = party.id, players = listOf(playerMatchingSdkUser)))
fire(DeletePlayerCommand(party.id, playerMatchingSdkUser.id))
}
} exercise {
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPinTest.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPinTest.kt
index a0024f0e02..6699c8ebc5 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPinTest.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPinTest.kt
@@ -4,7 +4,6 @@ import com.zegreatrob.coupling.action.party.DeletePartyCommand
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.pin.DeletePinCommand
-import com.zegreatrob.coupling.action.pin.SavePinCommand
import com.zegreatrob.coupling.action.pin.fire
import com.zegreatrob.coupling.model.pin.PinId
import com.zegreatrob.coupling.repository.validation.verifyWithWait
@@ -47,7 +46,7 @@ class SdkPinTest {
}
},
) exercise {
- pins.forEach { sdk.fire(SavePinCommand(party.id, it)) }
+ pins.forEach { sdk.fire(SavePartyCommand(partyId = party.id, pins = listOf(it))) }
} verifyWithWait {
sdk.fire(GqlQuery(PinListQuery(party.id)))
?.party
@@ -85,7 +84,7 @@ class SdkPinTest {
)
}
}) exercise {
- pins.forEach { sdk.fire(SavePinCommand(party.id, it)) }
+ pins.forEach { sdk.fire(SavePartyCommand(partyId = party.id, pins = listOf(it))) }
sdk.fire(DeletePinCommand(party.id, this.pins[1].id))
} verifyWithWait {
sdk.fire(GqlQuery(PinListQuery(party.id)))
@@ -105,7 +104,7 @@ class SdkPinTest {
suspend fun otherSdk() = altAuthorizedSdkDeferred.await()
}) {
otherSdk().fire(SavePartyCommand(otherParty))
- otherSdk().fire(SavePinCommand(otherParty.id, stubPin()))
+ otherSdk().fire(SavePartyCommand(partyId = otherParty.id, pins = listOf(stubPin())))
} exercise {
sdk().fire(GqlQuery(PinListQuery(otherParty.id)))
?.party
@@ -124,7 +123,7 @@ class SdkPinTest {
}) {
sdk = sdk()
sdk.fire(SavePartyCommand(party))
- sdk.fire(SavePinCommand(party.id, pin))
+ sdk.fire(SavePartyCommand(partyId = party.id, pins = listOf(pin)))
} exercise {
sdk.fire(GqlQuery(PinRecordListQuery(party.id)))
?.party
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPlayerTest.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPlayerTest.kt
index c642cdafa6..5a79297796 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPlayerTest.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkPlayerTest.kt
@@ -5,7 +5,6 @@ import com.zegreatrob.coupling.action.party.DeletePartyCommand
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
import com.zegreatrob.coupling.action.player.DeletePlayerCommand
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.player.PlayerId
import com.zegreatrob.coupling.repository.validation.assertHasIds
@@ -58,9 +57,9 @@ class SdkPlayerTest {
val updatedPlayer = player.copy(name = "Timmy!")
}
}) {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
} exercise {
- sdk.fire(SavePlayerCommand(party.id, updatedPlayer))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(updatedPlayer)))
sdk().fire(GqlQuery(PartyPlayersDetailsQuery(party.id)))
?.party
?.playerList
@@ -77,7 +76,7 @@ class SdkPlayerTest {
val player = stubPlayer()
}
}) {
- sdk.fire(SavePlayerCommand(partyId, player))
+ sdk.fire(SavePartyCommand(partyId = partyId, players = listOf(player)))
} exercise {
sdk.fire(DeletePlayerCommand(partyId, player.id))
sdk().fire(GqlQuery(PartyPlayersDetailsQuery(partyId)))
@@ -113,7 +112,7 @@ class SdkPlayerTest {
}
},
) {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
sdk.fire(DeletePlayerCommand(party.id, player.id))
} exercise {
sdk().fire(GqlQuery(PartyRetiredPlayersDetailsQuery(party.id)))
@@ -139,9 +138,9 @@ class SdkPlayerTest {
}
},
) {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
sdk.fire(DeletePlayerCommand(party.id, player.id))
- sdk.fire(SavePlayerCommand(party.id, similarPlayer))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(similarPlayer)))
sdk.fire(DeletePlayerCommand(party.id, similarPlayer.id))
} exercise {
sdk().fire(GqlQuery(PartyRetiredPlayersDetailsQuery(party.id)))
@@ -166,9 +165,9 @@ class SdkPlayerTest {
}
},
) {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
sdk.fire(DeletePlayerCommand(party.id, player.id))
- sdk.fire(SavePlayerCommand(party.id, player2))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player2)))
sdk.fire(DeletePlayerCommand(party.id, player2.id))
} exercise {
sdk().fire(GqlQuery(PartyRetiredPlayersDetailsQuery(party.id)))
@@ -188,9 +187,9 @@ class SdkPlayerTest {
val playerId = player.id
}
}) exercise {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
sdk.fire(DeletePlayerCommand(party.id, playerId))
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
sdk.fire(DeletePlayerCommand(party.id, playerId))
} verifyWithWait {
sdk().fire(GqlQuery(PartyRetiredPlayersDetailsQuery(party.id)))
@@ -208,7 +207,7 @@ class SdkPlayerTest {
val players = stubPlayers(3)
}
}) {
- players.forEach { setupScope.launch { sdk.fire(SavePlayerCommand(partyId, it)) } }
+ players.forEach { setupScope.launch { sdk.fire(SavePartyCommand(partyId = partyId, players = listOf(it))) } }
} exercise {
sdk().fire(GqlQuery(PartyPlayersDetailsQuery(partyId)))
?.party
@@ -227,7 +226,7 @@ class SdkPlayerTest {
}
}) {
coroutineScope {
- players.forEach { launch { sdk.fire(SavePlayerCommand(partyId, it)) } }
+ players.forEach { launch { sdk.fire(SavePartyCommand(partyId = partyId, players = listOf(it))) } }
}
} exercise {
sdk().fire(GqlQuery(PartySpinsUntilFullRotationQuery(partyId)))
@@ -251,7 +250,7 @@ class SdkPlayerTest {
)
}
}) {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
} exercise {
sdk().fire(GqlQuery(PartyPlayersDetailsQuery(party.id)))
?.party
@@ -273,8 +272,8 @@ class SdkPlayerTest {
}
}) {
sdk.fire(SavePartyCommand(stubPartyDetails().copy(id = partyId2)))
- sdk.fire(SavePlayerCommand(partyId, player1))
- sdk.fire(SavePlayerCommand(partyId2, player2))
+ sdk.fire(SavePartyCommand(partyId = partyId, players = listOf(player1)))
+ sdk.fire(SavePartyCommand(partyId = partyId2, players = listOf(player2)))
} exercise {
sdk().fire(GqlQuery(PartyPlayersDetailsQuery(partyId)))
?.party
@@ -294,7 +293,7 @@ class SdkPlayerTest {
val player = stubPlayer()
}
}) exercise {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
sdk.fire(DeletePlayerCommand(party.id, player.id))
sdk().fire(GqlQuery(PartyRetiredPlayersDataQuery(party.id)))
?.party
@@ -317,7 +316,7 @@ class SdkPlayerTest {
val player = stubPlayer()
}
}) exercise {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
sdk().fire(GqlQuery(PartyPlayersDataQuery(party.id)))
?.party
?.playerList
@@ -340,7 +339,7 @@ class SdkPlayerTest {
val party = stubPartyDetails()
}) {
otherSdk.fire(SavePartyCommand(party))
- otherSdk.fire(SavePlayerCommand(party.id, stubPlayer()))
+ otherSdk.fire(SavePartyCommand(partyId = party.id, players = listOf(stubPlayer())))
} exercise {
sdk.fire(GqlQuery(PartyPlayersDetailsQuery(party.id)))
?.party
@@ -367,7 +366,7 @@ class SdkPlayerTest {
}) {
otherSdk.fire(SavePartyCommand(party))
} exercise {
- sdk.fire(SavePlayerCommand(party.id, player))
+ sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
otherSdk.fire(GqlQuery(PartyPlayersDetailsQuery(party.id)))
?.party
?.playerList
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkUserTest.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkUserTest.kt
index ee52e6b75d..1611bd9ad6 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkUserTest.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SdkUserTest.kt
@@ -2,8 +2,6 @@ package com.zegreatrob.coupling.sdk
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.action.user.ConnectUserCommand
import com.zegreatrob.coupling.action.user.CreateConnectUserSecretCommand
import com.zegreatrob.coupling.action.user.DisconnectUserCommand
@@ -41,7 +39,7 @@ class SdkUserTest {
val player = stubPlayer().copy(email = PRIMARY_AUTHORIZED_USER_EMAIL)
}) {
sdk().fire(SavePartyCommand(party))
- sdk().fire(SavePlayerCommand(party.id, player))
+ sdk().fire(SavePartyCommand(partyId = party.id, players = listOf(player)))
} exercise {
sdk().fire(GqlQuery(UserPlayersQuery()))
} verify { result ->
diff --git a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SpinTest.kt b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SpinTest.kt
index e37c238764..6956ac22c3 100644
--- a/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SpinTest.kt
+++ b/sdk/src/commonTest/kotlin/com/zegreatrob/coupling/sdk/SpinTest.kt
@@ -7,10 +7,6 @@ import com.zegreatrob.coupling.action.pairassignmentdocument.fire
import com.zegreatrob.coupling.action.party.DeletePartyCommand
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.fire
-import com.zegreatrob.coupling.action.pin.SavePinCommand
-import com.zegreatrob.coupling.action.pin.fire
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.fire
import com.zegreatrob.coupling.model.forEach
import com.zegreatrob.coupling.model.get
import com.zegreatrob.coupling.model.map
@@ -63,7 +59,7 @@ class SpinTest {
}) {
coroutineScope {
sdk.fire(SavePartyCommand(party))
- players.forEach { launch { sdk.fire(SavePlayerCommand(party.id, it)) } }
+ players.forEach { launch { sdk.fire(SavePartyCommand(partyId = party.id, players = listOf(it))) } }
}
} exercise {
sdk.fire(SpinCommand(party.id, players.map { it.id }, emptyList()))
@@ -232,9 +228,9 @@ class SpinTest {
) = coroutineScope {
with(sdk) {
fire(SavePartyCommand(party))
- players.forEach { launch { fire(SavePlayerCommand(party.id, it)) } }
+ players.forEach { launch { fire(SavePartyCommand(partyId = party.id, players = listOf(it))) } }
history.forEach { launch { sdk.fire(SavePairAssignmentsCommand(party.id, it)) } }
- pins.forEach { launch { sdk.fire(SavePinCommand(party.id, it)) } }
+ pins.forEach { launch { sdk.fire(SavePartyCommand(partyId = party.id, pins = listOf(it))) } }
}
}
}
diff --git a/server/actionz/src/jsMain/kotlin/com/zegreatrob/coupling/server/action/party/ServerSavePartyCommandDispatcher.kt b/server/actionz/src/jsMain/kotlin/com/zegreatrob/coupling/server/action/party/ServerSavePartyCommandDispatcher.kt
index 1f5989006e..0cf8143333 100644
--- a/server/actionz/src/jsMain/kotlin/com/zegreatrob/coupling/server/action/party/ServerSavePartyCommandDispatcher.kt
+++ b/server/actionz/src/jsMain/kotlin/com/zegreatrob/coupling/server/action/party/ServerSavePartyCommandDispatcher.kt
@@ -5,6 +5,9 @@ import com.zegreatrob.coupling.action.VoidResult
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.model.PartyRecord
import com.zegreatrob.coupling.model.party.PartyDetails
+import com.zegreatrob.coupling.model.party.PartyElement
+import com.zegreatrob.coupling.model.party.PartyId
+import com.zegreatrob.coupling.model.pin.Pin
import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.coupling.model.user.CurrentUserProvider
import com.zegreatrob.coupling.model.user.UserDetails
@@ -12,6 +15,8 @@ import com.zegreatrob.coupling.repository.await
import com.zegreatrob.coupling.repository.party.PartyIdGetSyntax
import com.zegreatrob.coupling.repository.party.PartyRepository
import com.zegreatrob.coupling.repository.party.PartySaveSyntax
+import com.zegreatrob.coupling.repository.pin.PinSave
+import com.zegreatrob.coupling.repository.player.PlayerSave
import com.zegreatrob.coupling.server.action.user.UserSaveSyntax
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
@@ -29,6 +34,8 @@ interface ServerSavePartyCommandDispatcher :
CurrentUserProvider {
override val partyRepository: PartyRepository
+ val playerSaveRepository: PlayerSave
+ val pinSaveRepository: PinSave
override suspend fun perform(command: SavePartyCommand) = if (command.isAuthorizedToSave()) {
command.savePartyAndUser()
@@ -38,11 +45,15 @@ interface ServerSavePartyCommandDispatcher :
}
private suspend fun SavePartyCommand.savePartyAndUser() = withContext(currentCoroutineContext()) {
- launch { party.save() }
- launch {
- currentUser.copy(authorizedPartyIds = currentUser.authorizedPartyIds + party.id)
- .saveIfUserChanged()
+ party?.let { partyDetails ->
+ launch { partyDetails.save() }
+ launch {
+ currentUser.copy(authorizedPartyIds = currentUser.authorizedPartyIds + partyDetails.id)
+ .saveIfUserChanged()
+ }
}
+ launch { players.forEach { playerSaveRepository.save(PartyElement(partyId, it)) } }
+ launch { pins.forEach { pinSaveRepository.save(PartyElement(partyId, it)) } }
}
private suspend fun UserDetails.saveIfUserChanged() = if (this != currentUser) save() else Unit
@@ -51,11 +62,15 @@ interface ServerSavePartyCommandDispatcher :
val (connectedUsers, loadedParty, players) = coroutineScope {
await(
async { loadCurrentConnectedUsers() },
- async { party.id.get() },
+ async { partyId.get() },
async { currentUser.loadPlayers() },
)
}
- return loadedParty.partyIsNew() || authorizedPartyIds(connectedUsers, players).contains(party.id)
+ val isNewParty = loadedParty.partyIsNew()
+ if (isNewParty && party == null) {
+ return false
+ }
+ return isNewParty || authorizedPartyIds(connectedUsers, players).contains(partyId)
}
private fun authorizedPartyIds(users: List, players: List>) = players.map { it.data.partyId } + users.flatMap { it.authorizedPartyIds }
diff --git a/server/actionz/src/jsTest/kotlin/com/zegreatrob/coupling/server/action/party/SavePartyCommandTest.kt b/server/actionz/src/jsTest/kotlin/com/zegreatrob/coupling/server/action/party/SavePartyCommandTest.kt
new file mode 100644
index 0000000000..b2453da35f
--- /dev/null
+++ b/server/actionz/src/jsTest/kotlin/com/zegreatrob/coupling/server/action/party/SavePartyCommandTest.kt
@@ -0,0 +1,95 @@
+package com.zegreatrob.coupling.server.action.party
+
+import com.zegreatrob.coupling.action.VoidResult
+import com.zegreatrob.coupling.action.party.SavePartyCommand
+import com.zegreatrob.coupling.model.Record
+import com.zegreatrob.coupling.model.party.PartyDetails
+import com.zegreatrob.coupling.model.party.PartyElement
+import com.zegreatrob.coupling.model.party.PartyId
+import com.zegreatrob.coupling.model.party.PartyIntegration
+import com.zegreatrob.coupling.model.pin.Pin
+import com.zegreatrob.coupling.model.player.Badge
+import com.zegreatrob.coupling.model.player.Player
+import com.zegreatrob.coupling.model.user.UserDetails
+import com.zegreatrob.coupling.repository.party.PartyRepository
+import com.zegreatrob.coupling.repository.pin.PinSave
+import com.zegreatrob.coupling.repository.player.PlayerListGetByEmail
+import com.zegreatrob.coupling.repository.player.PlayerSave
+import com.zegreatrob.coupling.repository.user.UserRepository
+import com.zegreatrob.coupling.stubmodel.stubPlayer
+import com.zegreatrob.coupling.stubmodel.stubUserDetails
+import com.zegreatrob.minassert.assertIsEqualTo
+import com.zegreatrob.minspy.Spy
+import com.zegreatrob.minspy.SpyData
+import com.zegreatrob.minspy.spyFunction
+import com.zegreatrob.testmints.async.asyncSetup
+import kotools.types.text.NotBlankString
+import kotlin.test.Test
+import kotlin.time.Clock
+
+class SavePartyCommandTest {
+
+ @Test
+ fun willSavePlayersToRepository() = asyncSetup(object : ServerSavePartyCommandDispatcher {
+ val partyId = PartyId("woo")
+ val player = stubPlayer().copy(
+ badge = Badge.Default,
+ name = "Tim",
+ email = "tim@tim.meat",
+ callSignAdjective = "Spicy",
+ callSignNoun = "Meatball",
+ imageURL = "italian.jpg",
+ avatarType = null,
+ )
+
+ override val currentUser: UserDetails = stubUserDetails().copy(authorizedPartyIds = setOf(partyId))
+ override val userId = currentUser.id
+
+ override val playerSaveRepository = PlayerSaverSpy().apply { whenever(PartyElement(partyId, player), Unit) }
+ override val pinSaveRepository = PinSaverSpy()
+ override val playerRepository = EmptyPlayerRepository
+ override val partyRepository = ExistingPartyRepository()
+ override val userRepository = EmptyUserRepository
+ }) exercise {
+ perform(SavePartyCommand(partyId = partyId, players = listOf(player)))
+ } verify { result ->
+ result.assertIsEqualTo(VoidResult.Accepted)
+ playerSaveRepository.spyReceivedValues
+ .assertIsEqualTo(listOf(PartyElement(partyId, player)))
+ }
+
+ private class PlayerSaverSpy :
+ PlayerSave,
+ Spy, Unit> by SpyData() {
+ override suspend fun save(partyPlayer: PartyElement) = spyFunction(partyPlayer)
+ }
+
+ private class PinSaverSpy : PinSave {
+ override suspend fun save(partyPin: PartyElement) = Unit
+ }
+
+ private object EmptyPlayerRepository : PlayerListGetByEmail {
+ override suspend fun getPlayersByEmail(emails: List) = emptyList>()
+ }
+
+ private object EmptyUserRepository : UserRepository {
+ override suspend fun save(user: UserDetails) = Unit
+ override suspend fun getUser(): Record? = null
+ override suspend fun getUsersWithEmail(email: NotBlankString) = emptyList>()
+ }
+
+ private class ExistingPartyRepository : PartyRepository {
+ override suspend fun getDetails(partyId: PartyId) = Record(
+ data = PartyDetails(id = partyId),
+ modifyingUserId = null,
+ isDeleted = false,
+ timestamp = Clock.System.now(),
+ )
+
+ override suspend fun getIntegration(partyId: PartyId): Record? = null
+ override suspend fun loadParties(partyIds: Set) = emptyList>()
+ override suspend fun save(party: PartyDetails) = Unit
+ override suspend fun save(integration: PartyElement) = Unit
+ override suspend fun deleteIt(partyId: PartyId) = false
+ }
+}
diff --git a/server/actionz/src/jsTest/kotlin/com/zegreatrob/coupling/server/action/player/SavePlayerCommandTest.kt b/server/actionz/src/jsTest/kotlin/com/zegreatrob/coupling/server/action/player/SavePlayerCommandTest.kt
deleted file mode 100644
index 0975a9445a..0000000000
--- a/server/actionz/src/jsTest/kotlin/com/zegreatrob/coupling/server/action/player/SavePlayerCommandTest.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.zegreatrob.coupling.server.action.player
-
-import com.zegreatrob.coupling.action.VoidResult
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.model.party.PartyElement
-import com.zegreatrob.coupling.model.party.PartyId
-import com.zegreatrob.coupling.model.party.with
-import com.zegreatrob.coupling.model.player.Badge
-import com.zegreatrob.coupling.model.player.Player
-import com.zegreatrob.coupling.repository.player.PlayerSave
-import com.zegreatrob.coupling.stubmodel.stubPlayer
-import com.zegreatrob.minassert.assertIsEqualTo
-import com.zegreatrob.minspy.Spy
-import com.zegreatrob.minspy.SpyData
-import com.zegreatrob.minspy.spyFunction
-import com.zegreatrob.testmints.async.asyncSetup
-import kotlin.test.Test
-
-class SavePlayerCommandTest {
-
- @Test
- fun willSaveToRepository() = asyncSetup(object : ServerSavePlayerCommandDispatcher {
- override val currentPartyId = PartyId("woo")
- val player = stubPlayer().copy(
- badge = Badge.Default,
- name = "Tim",
- email = "tim@tim.meat",
- callSignAdjective = "Spicy",
- callSignNoun = "Meatball",
- imageURL = "italian.jpg",
- avatarType = null,
- )
- override val playerRepository = PlayerSaverSpy().apply { whenever(currentPartyId.with(player), Unit) }
- }) exercise {
- perform(SavePlayerCommand(currentPartyId, player))
- } verify { result ->
- result.assertIsEqualTo(VoidResult.Accepted)
- playerRepository.spyReceivedValues
- .assertIsEqualTo(listOf(currentPartyId.with(player)))
- }
-
- class PlayerSaverSpy :
- PlayerSave,
- Spy, Unit> by SpyData() {
- override suspend fun save(partyPlayer: PartyElement) = spyFunction(partyPlayer)
- }
-}
diff --git a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/CommandDispatcher.kt b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/CommandDispatcher.kt
index bc34e4932c..13c2ff85be 100644
--- a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/CommandDispatcher.kt
+++ b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/CommandDispatcher.kt
@@ -45,7 +45,6 @@ import com.zegreatrob.coupling.server.action.party.PartyIntegrationQuery
import com.zegreatrob.coupling.server.action.party.ServerDeletePartyCommandDispatcher
import com.zegreatrob.coupling.server.action.pin.PinsQuery
import com.zegreatrob.coupling.server.action.pin.ServerDeletePinCommandDispatcher
-import com.zegreatrob.coupling.server.action.pin.ServerSavePinCommandDispatcher
import com.zegreatrob.coupling.server.action.player.PairAssignmentHistoryQuery
import com.zegreatrob.coupling.server.action.player.PairListQuery
import com.zegreatrob.coupling.server.action.player.PairQuery
@@ -54,7 +53,6 @@ import com.zegreatrob.coupling.server.action.player.RecentTimesPairedQuery
import com.zegreatrob.coupling.server.action.player.RetiredPlayersQuery
import com.zegreatrob.coupling.server.action.player.ServerDeletePlayerCommandDispatcher
import com.zegreatrob.coupling.server.action.player.ServerPairCountQueryDispatcher
-import com.zegreatrob.coupling.server.action.player.ServerSavePlayerCommandDispatcher
import com.zegreatrob.coupling.server.action.player.ServerSpinsSinceLastPairedQueryDispatcher
import com.zegreatrob.coupling.server.action.player.SpinsUntilFullRotationQuery
import com.zegreatrob.coupling.server.action.player.UserPlayersQuery
@@ -137,6 +135,8 @@ class CommandDispatcher(
TraceIdProvider,
BroadcastAction.Dispatcher,
ConnectPartyUserCommand.Dispatcher {
+ override val playerSaveRepository get() = playerRepository
+ override val pinSaveRepository get() = pinRepository
override val cannon: ActionCannon = ActionCannon(this, LoggingActionPipe(traceId))
override val secretGenerator = object : JwtSecretHandler {
override val secretIssuer: String = Config.publicUrl
@@ -181,7 +181,6 @@ class CurrentPartyDispatcher(
ServerSpinCommandDispatcher,
ServerSaveSlackIntegrationCommandDispatcher,
ServerCreateSecretCommandDispatcher,
- ServerSavePlayerCommandDispatcher,
ServerDeletePlayerCommandDispatcher,
ServerDeleteSecretCommandDispatcher,
RetiredPlayersQuery.Dispatcher,
@@ -189,7 +188,6 @@ class CurrentPartyDispatcher(
ServerDeletePairAssignmentsCommandDispatcher,
ServerDeletePartyCommandDispatcher,
ServerDeletePinCommandDispatcher,
- ServerSavePinCommandDispatcher,
CurrentConnectedUsersProvider,
CannonProvider {
override val userId: UserId get() = commandDispatcher.userId
diff --git a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/party/SavePartyResolver.kt b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/party/SavePartyResolver.kt
index 6cddd3e3dd..f389eb3ab6 100644
--- a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/party/SavePartyResolver.kt
+++ b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/party/SavePartyResolver.kt
@@ -3,7 +3,7 @@ package com.zegreatrob.coupling.server.entity.party
import com.zegreatrob.coupling.action.party.SavePartyCommand
import com.zegreatrob.coupling.action.party.perform
import com.zegreatrob.coupling.json.GqlSavePartyInput
-import com.zegreatrob.coupling.json.toModel
+import com.zegreatrob.coupling.json.toCommand
import com.zegreatrob.coupling.server.entity.boost.requiredInput
import com.zegreatrob.coupling.server.graphql.DispatcherProviders.command
import com.zegreatrob.coupling.server.graphql.dispatch
@@ -11,7 +11,7 @@ import kotlinx.serialization.json.JsonNull
val savePartyResolver = dispatch(
dispatcherFunc = command(),
- commandFunc = requiredInput { _: JsonNull, input: GqlSavePartyInput -> SavePartyCommand(input.toModel()) },
+ commandFunc = requiredInput { _: JsonNull, input: GqlSavePartyInput -> input.toCommand() },
fireFunc = ::perform,
toSerializable = { true },
)
diff --git a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/pin/SavePinResolver.kt b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/pin/SavePinResolver.kt
index 724b3c5832..bd3cc1dfaf 100644
--- a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/pin/SavePinResolver.kt
+++ b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/pin/SavePinResolver.kt
@@ -1,7 +1,7 @@
package com.zegreatrob.coupling.server.entity.pin
-import com.zegreatrob.coupling.action.pin.SavePinCommand
-import com.zegreatrob.coupling.action.pin.perform
+import com.zegreatrob.coupling.action.party.SavePartyCommand
+import com.zegreatrob.coupling.action.party.perform
import com.zegreatrob.coupling.json.GqlSavePinInput
import com.zegreatrob.coupling.model.pin.Pin
import com.zegreatrob.coupling.server.entity.boost.requiredInput
@@ -21,7 +21,10 @@ val savePinResolver = dispatch(
toSerializable = { true },
)
-private fun GqlSavePinInput.toCommand() = SavePinCommand(partyId, toPin())
+private fun GqlSavePinInput.toCommand() = SavePartyCommand(
+ partyId = partyId,
+ pins = listOf(toPin()),
+)
private fun GqlSavePinInput.toPin() = Pin(
id = pinId,
diff --git a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/player/SavePlayerResolver.kt b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/player/SavePlayerResolver.kt
index f5fa6595ec..9f8ca7b469 100644
--- a/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/player/SavePlayerResolver.kt
+++ b/server/src/jsMain/kotlin/com/zegreatrob/coupling/server/entity/player/SavePlayerResolver.kt
@@ -1,7 +1,7 @@
package com.zegreatrob.coupling.server.entity.player
-import com.zegreatrob.coupling.action.player.SavePlayerCommand
-import com.zegreatrob.coupling.action.player.perform
+import com.zegreatrob.coupling.action.party.SavePartyCommand
+import com.zegreatrob.coupling.action.party.perform
import com.zegreatrob.coupling.json.GqlSavePlayerInput
import com.zegreatrob.coupling.json.toModel
import com.zegreatrob.coupling.server.entity.boost.requiredInput
@@ -21,4 +21,7 @@ val savePlayerResolver = dispatch(
toSerializable = { true },
)
-private fun GqlSavePlayerInput.command() = SavePlayerCommand(partyId, toModel())
+private fun GqlSavePlayerInput.command() = SavePartyCommand(
+ partyId = partyId,
+ players = listOf(toModel()),
+)
diff --git a/server/src/jsMain/resources/schema.graphqls b/server/src/jsMain/resources/schema.graphqls
index b011588e73..eb5e866ddc 100644
--- a/server/src/jsMain/resources/schema.graphqls
+++ b/server/src/jsMain/resources/schema.graphqls
@@ -270,6 +270,12 @@ input SaveSlackIntegrationInput {
input SavePartyInput {
partyId: PartyId!
+ party: SavePartyDetailsInput
+ players: SavePartyPlayersInput
+ pins: SavePartyPinsInput
+}
+
+input SavePartyDetailsInput {
name: String
email: String
pairingRule: Int
@@ -281,6 +287,32 @@ input SavePartyInput {
animationSpeed: Float
}
+input SavePartyPlayersInput {
+ items: [SavePartyPlayerInput!]!
+}
+
+input SavePartyPinsInput {
+ items: [SavePartyPinInput!]!
+}
+
+input SavePartyPlayerInput {
+ playerId: PlayerId!
+ name: String!
+ email: String!
+ badge: Badge!
+ callSignAdjective: String!
+ callSignNoun: String!
+ imageURL: String
+ avatarType: String
+ unvalidatedEmails: [String!]!
+}
+
+input SavePartyPinInput {
+ pinId: PinId!
+ icon: String!
+ name: String!
+}
+
input SavePlayerInput {
partyId: PartyId!
playerId: PlayerId!
@@ -392,9 +424,9 @@ type Mutation {
saveParty(input: SavePartyInput!): Boolean
deleteParty(input: DeletePartyInput!): Boolean
saveSlackIntegration(input: SaveSlackIntegrationInput!): Boolean
- savePin(input: SavePinInput!): Boolean
+ savePin(input: SavePinInput!): Boolean @deprecated(reason: "Use saveParty with pins input.")
deletePin(input: DeletePinInput!): Boolean
- savePlayer(input: SavePlayerInput!): Boolean
+ savePlayer(input: SavePlayerInput!): Boolean @deprecated(reason: "Use saveParty with players input.")
deletePlayer(input: DeletePlayerInput!): Boolean
savePairAssignments(input: SavePairAssignmentsInput!): Boolean
deletePairAssignments(input: DeletePairAssignmentsInput!): Boolean