summaryrefslogtreecommitdiff
path: root/sw-ui-kt
diff options
context:
space:
mode:
authorJoffrey Bion <joffrey.bion@booking.com>2020-03-22 23:06:19 +0100
committerJoffrey Bion <joffrey.bion@booking.com>2020-03-22 23:16:59 +0100
commit7730a8ad565c167029681fd15d98be6c7dce0492 (patch)
tree9f0edfc7174298d36d717586aaf35ef961d1f0f5 /sw-ui-kt
parentFix home refresh on enter key (diff)
downloadseven-wonders-7730a8ad565c167029681fd15d98be6c7dce0492.tar.gz
seven-wonders-7730a8ad565c167029681fd15d98be6c7dce0492.tar.bz2
seven-wonders-7730a8ad565c167029681fd15d98be6c7dce0492.zip
Migrate game browser to blueprint components
Diffstat (limited to 'sw-ui-kt')
-rw-r--r--sw-ui-kt/src/main/kotlin/blueprintjs.kt73
-rw-r--r--sw-ui-kt/src/main/kotlin/blueprintjsHelpers.kt46
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt53
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt76
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/home/ChooseNameForm.kt4
-rw-r--r--sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt4
6 files changed, 182 insertions, 74 deletions
diff --git a/sw-ui-kt/src/main/kotlin/blueprintjs.kt b/sw-ui-kt/src/main/kotlin/blueprintjs.kt
index 37892fde..81227835 100644
--- a/sw-ui-kt/src/main/kotlin/blueprintjs.kt
+++ b/sw-ui-kt/src/main/kotlin/blueprintjs.kt
@@ -1,8 +1,6 @@
@file:JsModule("@blueprintjs/core")
package com.palantir.blueprintjs
-import org.w3c.dom.HTMLAnchorElement
-import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.events.Event
@@ -158,6 +156,8 @@ external class Icon : PureComponent<IIconProps, RState> {
}
external interface IButtonProps : IActionProps {
+ // artificially added to allow title on button (should probably be on more general props)
+ var title: String?
/**
* If set to `true`, the button will display in an active state.
* This is equivalent to setting `className={Classes.ACTIVE}`.
@@ -258,3 +258,72 @@ external interface IInputGroupState : RState {
external class InputGroup : PureComponent<IInputGroupProps, IInputGroupState> {
override fun render(): ReactElement
}
+
+external interface ITagProps : IProps, IIntentProps {
+ /**
+ * Whether the tag should appear in an active state.
+ * @default false
+ */
+ var active: Boolean?
+ /**
+ * Whether the tag should take up the full width of its container.
+ * @default false
+ */
+ var fill: Boolean?
+ /** Name of a Blueprint UI icon (or an icon element) to render before the children. */
+ var icon: IconName?
+ /**
+ * Whether the tag should visually respond to user interactions. If set
+ * to `true`, hovering over the tag will change its color and mouse cursor.
+ *
+ * Recommended when `onClick` is also defined.
+ *
+ * @default false
+ */
+ var interactive: Boolean?
+ /**
+ * Whether this tag should use large styles.
+ * @default false
+ */
+ var large: Boolean?
+ /**
+ * Whether this tag should use minimal styles.
+ * @default false
+ */
+ var minimal: Boolean?
+ /**
+ * Whether tag content should be allowed to occupy multiple lines.
+ * If false, a single line of text will be truncated with an ellipsis if
+ * it overflows. Note that icons will be vertically centered relative to
+ * multiline text.
+ * @default false
+ */
+ var multiline: Boolean?
+ /**
+ * Callback invoked when the tag is clicked.
+ * Recommended when `interactive` is `true`.
+ */
+ var onClick: ((e: MouseEvent) -> Unit)?;
+ /**
+ * Click handler for remove button.
+ * The remove button will only be rendered if this prop is defined.
+ */
+ var onRemove: ((e: MouseEvent, tagProps: ITagProps) -> Unit)?
+ /** Name of a Blueprint UI icon (or an icon element) to render after the children. */
+ var rightIcon: IconName?
+ /**
+ * Whether this tag should have rounded ends.
+ * @default false
+ */
+ var round: Boolean?
+}
+
+external class Tag : PureComponent<ITagProps, RState> {
+ override fun render(): ReactElement
+}
+
+external class Classes {
+ companion object {
+ val HTML_TABLE: String = definedExternally
+ }
+}
diff --git a/sw-ui-kt/src/main/kotlin/blueprintjsHelpers.kt b/sw-ui-kt/src/main/kotlin/blueprintjsHelpers.kt
index 5344b64e..0d9cb9bd 100644
--- a/sw-ui-kt/src/main/kotlin/blueprintjsHelpers.kt
+++ b/sw-ui-kt/src/main/kotlin/blueprintjsHelpers.kt
@@ -1,21 +1,21 @@
package com.palantir.blueprintjs
-import org.w3c.dom.HTMLElement
import org.w3c.dom.events.Event
import org.w3c.dom.events.MouseEvent
import react.RBuilder
-import react.RElementBuilder
import react.RHandler
import react.ReactElement
typealias IconName = String
-fun RBuilder.icon(
+fun RBuilder.bpIcon(
name: IconName,
size: Int = Icon.SIZE_STANDARD,
intent: Intent = Intent.NONE,
title: String? = null,
- alt: String? = null
+ alt: String? = null,
+ className: String? = null,
+ block: RHandler<IIconProps> = {}
): ReactElement = child(Icon::class) {
attrs {
this.icon = name
@@ -23,13 +23,16 @@ fun RBuilder.icon(
this.htmlTitle = title
this.intent = intent
this.title = alt
+ this.className = className
}
+ block()
}
fun RBuilder.bpButton(
minimal: Boolean = false,
large: Boolean = false,
disabled: Boolean = false,
+ title: String? = null,
icon: IconName? = null,
rightIcon: IconName? = null,
intent: Intent = Intent.NONE,
@@ -37,6 +40,7 @@ fun RBuilder.bpButton(
block: RHandler<IButtonProps> = {}
): ReactElement = child(Button::class) {
attrs {
+ this.title = title
this.minimal = minimal
this.large = large
this.disabled = disabled
@@ -48,7 +52,7 @@ fun RBuilder.bpButton(
block()
}
-fun RBuilder.inputGroup(
+fun RBuilder.bpInputGroup(
large: Boolean = false,
placeholder: String = "",
rightElement: ReactElement? = null,
@@ -62,22 +66,16 @@ fun RBuilder.inputGroup(
}
}
-data class ButtonProps(
- override var className: String? = null,
- override var intent: Intent? = Intent.NONE,
- override var disabled: Boolean? = false,
- override var icon: IconName? = null,
- override var onClick: ((event: MouseEvent) -> Unit)? = null,
- override var text: String? = null,
- override var active: Boolean? = true,
- override var alignText: Alignment? = null,
- override var elementRef: ((ref: HTMLElement?) -> Any)? = null,
- override var fill: Boolean? = null,
- override var large: Boolean? = null,
- override var loading: Boolean? = null,
- override var minimal: Boolean? = null,
- override var outlined: Boolean? = null,
- override var rightIcon: IconName? = null,
- override var small: Boolean? = null,
- override var type: String? = null
-) : IButtonProps
+fun RBuilder.bpTag(
+ intent: Intent? = null,
+ minimal: Boolean? = null,
+ active: Boolean? = null,
+ block: RHandler<ITagProps> = {}
+): ReactElement = child(Tag::class) {
+ attrs {
+ this.intent = intent
+ this.minimal = minimal
+ this.active = active
+ }
+ block()
+}
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt
index 318f49f4..c1bbf460 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/CreateGameForm.kt
@@ -1,17 +1,28 @@
package org.luxons.sevenwonders.ui.components.gameBrowser
-import kotlinx.html.InputType
-import kotlinx.html.js.onChangeFunction
+import com.palantir.blueprintjs.Intent
+import com.palantir.blueprintjs.bpButton
+import com.palantir.blueprintjs.bpInputGroup
+import com.palantir.blueprintjs.org.luxons.sevenwonders.ui.utils.createElement
+import kotlinx.css.Display
+import kotlinx.css.FlexDirection
+import kotlinx.css.JustifyContent
+import kotlinx.css.display
+import kotlinx.css.flexDirection
+import kotlinx.css.justifyContent
import kotlinx.html.js.onSubmitFunction
import org.luxons.sevenwonders.ui.redux.RequestCreateGameAction
import org.luxons.sevenwonders.ui.redux.connectDispatch
import org.w3c.dom.HTMLInputElement
+import org.w3c.dom.events.Event
import react.RBuilder
import react.RClass
import react.RComponent
import react.RProps
import react.RState
import react.dom.*
+import styled.css
+import styled.styledDiv
private interface CreateGameFormProps: RProps {
var createGame: (String) -> Unit
@@ -26,22 +37,40 @@ private class CreateGameForm(props: CreateGameFormProps): RComponent<CreateGameF
}
override fun RBuilder.render() {
- form {
- attrs.onSubmitFunction = { props.createGame(state.gameName) }
-
- input(type = InputType.text) {
+ styledDiv {
+ css {
+ display = Display.flex
+ flexDirection = FlexDirection.row
+ justifyContent = JustifyContent.spaceBetween
+ }
+ form {
attrs {
- value = state.gameName
- onChangeFunction = { e ->
+ onSubmitFunction = { e -> createGame(e) }
+ }
+
+ bpInputGroup(
+ placeholder = "Game name",
+ onChange = { e ->
val input = e.currentTarget as HTMLInputElement
setState(transformState = { CreateGameFormState(input.value) })
- }
- }
+ },
+ rightElement = createGameButton()
+ )
}
-
- input(type = InputType.submit) {}
+ // TODO
+ div { +"PLAYER INFO HERE" }
+ //playerInfo()
}
}
+
+ private fun createGameButton() = createElement {
+ bpButton(minimal = true, intent = Intent.PRIMARY, icon = "add", onClick = { e -> createGame(e) })
+ }
+
+ private fun createGame(e: Event) {
+ e.preventDefault() // prevents refreshing the page when pressing Enter
+ props.createGame(state.gameName)
+ }
}
val createGameForm: RClass<RProps> = connectDispatch(CreateGameForm::class) { dispatch, _ ->
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
index 206ef749..e32409e4 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/gameBrowser/GameList.kt
@@ -1,8 +1,19 @@
package org.luxons.sevenwonders.ui.components.gameBrowser
+import com.palantir.blueprintjs.Classes
+import com.palantir.blueprintjs.Intent
+import com.palantir.blueprintjs.bpButton
+import com.palantir.blueprintjs.bpIcon
+import com.palantir.blueprintjs.bpTag
+import kotlinx.css.Align
+import kotlinx.css.Display
+import kotlinx.css.FlexDirection
import kotlinx.css.VerticalAlign
+import kotlinx.css.alignItems
+import kotlinx.css.display
+import kotlinx.css.flexDirection
import kotlinx.css.verticalAlign
-import kotlinx.html.js.onClickFunction
+import kotlinx.html.classes
import kotlinx.html.title
import org.luxons.sevenwonders.model.api.LobbyDTO
import org.luxons.sevenwonders.model.api.State
@@ -14,7 +25,9 @@ import react.RProps
import react.RState
import react.dom.*
import styled.css
+import styled.styledDiv
import styled.styledSpan
+import styled.styledTr
interface GameListStateProps : RProps {
var games: List<LobbyDTO>
@@ -30,6 +43,9 @@ class GameListPresenter(props: GameListProps) : RComponent<GameListProps, RState
override fun RBuilder.render() {
table {
+ attrs {
+ classes = setOf(Classes.HTML_TABLE)
+ }
thead {
gameListHeaderRow()
}
@@ -49,58 +65,54 @@ private fun RBuilder.gameListHeaderRow() = tr {
th { +"Join" }
}
-private fun RBuilder.gameListItemRow(lobby: LobbyDTO, joinGame: (Long) -> Unit) = tr {
+private fun RBuilder.gameListItemRow(lobby: LobbyDTO, joinGame: (Long) -> Unit) = styledTr {
+ css {
+ verticalAlign = VerticalAlign.middle
+ }
attrs {
key = lobby.id.toString()
}
- th { +lobby.name }
- th { gameStatus(lobby.state) }
- th { playerCount(lobby.players.size) }
- th { joinButton(lobby, joinGame) }
+ td { +lobby.name }
+ td { gameStatus(lobby.state) }
+ td { playerCount(lobby.players.size) }
+ td { joinButton(lobby, joinGame) }
}
private fun RBuilder.gameStatus(state: State) {
- // TODO
- // <Tag minimal intent={statusIntents[state]}>{state}</Tag>
- // const statusIntents = {
- // 'LOBBY': Intent.SUCCESS,
- // 'PLAYING': Intent.WARNING,
- // };
- span {
+ val intent = when(state) {
+ State.LOBBY -> Intent.SUCCESS
+ State.PLAYING -> Intent.WARNING
+ }
+ bpTag(minimal = true, intent = intent) {
+state.toString()
}
}
private fun RBuilder.playerCount(nPlayers: Int) {
- //<div title='Number of players'>
- // <Icon className="playerCountIcon" icon="people" title={false} />
- // <span className="playerCount"> {nbPlayers}</span>
- //</div>;
-
- // CSS:
- // .playerCountIcon, .playerCount {
- // vertical-align: middle;
- // }
- div {
+ styledDiv {
+ css {
+ display = Display.flex
+ flexDirection = FlexDirection.row
+ alignItems = Align.center
+ }
attrs {
title = "Number of players"
}
+ bpIcon(name = "people", title = null)
styledSpan {
- css {
- verticalAlign = VerticalAlign.middle
- }
+nPlayers.toString()
}
}
}
private fun RBuilder.joinButton(lobby: LobbyDTO, joinGame: (Long) -> Unit) {
- button {
- attrs {
- disabled = lobby.state != State.LOBBY
- onClickFunction = { joinGame(lobby.id) }
- }
- }
+ bpButton(
+ minimal = true,
+ title = "Join Game",
+ icon = "arrow-right",
+ disabled = lobby.state != State.LOBBY,
+ onClick = { joinGame(lobby.id) }
+ )
}
val gameList = connect<GameListStateProps, GameListDispatchProps, GameListProps>(
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/home/ChooseNameForm.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/home/ChooseNameForm.kt
index 91f6e291..b0a7b5e2 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/home/ChooseNameForm.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/home/ChooseNameForm.kt
@@ -2,7 +2,7 @@ package org.luxons.sevenwonders.ui.components.home
import com.palantir.blueprintjs.Intent
import com.palantir.blueprintjs.bpButton
-import com.palantir.blueprintjs.inputGroup
+import com.palantir.blueprintjs.bpInputGroup
import com.palantir.blueprintjs.org.luxons.sevenwonders.ui.utils.createElement
import kotlinx.html.js.onSubmitFunction
import org.luxons.sevenwonders.ui.redux.RequestChooseName
@@ -32,7 +32,7 @@ private class ChooseNameForm(props: ChooseNameFormProps): RComponent<ChooseNameF
override fun RBuilder.render() {
form {
attrs.onSubmitFunction = { e -> chooseUsername(e) }
- inputGroup(
+ bpInputGroup(
large = true,
placeholder = "Username",
rightElement = submitButton(),
diff --git a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt
index f096c5db..7c6d688f 100644
--- a/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt
+++ b/sw-ui-kt/src/main/kotlin/org/luxons/sevenwonders/ui/components/lobby/RadialPlayerList.kt
@@ -2,7 +2,7 @@ package org.luxons.sevenwonders.ui.components.lobby
import com.palantir.blueprintjs.IconName
import com.palantir.blueprintjs.Intent
-import com.palantir.blueprintjs.icon
+import com.palantir.blueprintjs.bpIcon
import kotlinx.css.Align
import kotlinx.css.Display
import kotlinx.css.FlexDirection
@@ -104,5 +104,5 @@ private fun RBuilder.playerPlaceholder(): ReactElement = styledDiv {
private fun RBuilder.userIcon(isUser: Boolean, isOwner: Boolean, title: String?): ReactElement {
val iconName: IconName = if (isOwner) "badge" else "user"
val intent: Intent = if (isUser) Intent.WARNING else Intent.NONE
- return icon(name = iconName, intent = intent, size = 50, title = title)
+ return bpIcon(name = iconName, intent = intent, size = 50, title = title)
}
bgstack15