Skip to content

Commit

Permalink
Merge pull request #1 from dborisenko/react-trello
Browse files Browse the repository at this point in the history
React trello
  • Loading branch information
dborisenko committed Oct 26, 2018
2 parents 375430f + 2484b51 commit 0ae257b
Show file tree
Hide file tree
Showing 12 changed files with 445 additions and 2 deletions.
30 changes: 30 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,34 @@ lazy val `react-sortable-hoc` = project
wartremoverErrors in (Test, compile) := Warts.allBut(Wart.Any, Wart.NonUnitStatements, Wart.Nothing)
)

lazy val `react-trello` = project
.in(file("react-trello"))
.enablePlugins(ScalaJSPlugin)
.enablePlugins(ScalaJSBundlerPlugin)
.settings(commonSettings)
.settings(publishSettings)
.settings(
libraryDependencies ++= Seq(
Dependencies.`scalajs-react-core`.value,
Dependencies.`scalacss-ext-react`.value,
Dependencies.`scalajs-react-test`.value % Test,
Dependencies.specs2.value % Test
),
npmDependencies in Test := Seq(
Dependencies.`react-trello`,
Dependencies.`babel-runtime`,
Dependencies.react,
Dependencies.`react-dom`
),
(org.scalajs.sbtplugin.ScalaJSPluginInternal.scalaJSRequestsDOM in Test) := true
)
.settings(
wartremoverErrors in (Compile, compile) := Warts
.allBut(Wart.MutableDataStructures, Wart.Any, Wart.AsInstanceOf, Wart.DefaultArguments, Wart.Nothing),
wartremoverErrors in (Test, compile) := Warts.allBut(Wart.Any, Wart.NonUnitStatements, Wart.Nothing)
)
.dependsOn(macros)

lazy val `scalajs-react-components` = project
.in(file("."))
.settings(commonSettings)
Expand All @@ -292,5 +320,7 @@ lazy val `scalajs-react-components` = project
.aggregate(`generator-semantic-ui-react`)
.aggregate(`semantic-ui-react`)
.aggregate(`react-sortable-hoc`)
.aggregate(`react-trello`)
.dependsOn(`semantic-ui-react`)
.dependsOn(`react-sortable-hoc`)
.dependsOn(`react-trello`)
8 changes: 6 additions & 2 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ object Dependencies extends DependencyBuilders {

// Scala: JS libraries
lazy val `scalajs-react` = "1.3.1"
lazy val scalacss = "0.5.5"

// Scala: JVM + JS libraries
lazy val scalatest = "3.0.5"
Expand All @@ -24,7 +25,8 @@ object Dependencies extends DependencyBuilders {
lazy val `semantic-ui-react` = "0.82.5"
lazy val react = "16.5.2"
lazy val `react-sortable-hoc` = "0.8.3"
lazy val `react-beautiful-dnd` = "9.0.2"
lazy val `react-trello` = "2.0.1"
lazy val `babel-runtime` = "7.1.2"
}

// Scala: JVM libraries
Expand All @@ -34,6 +36,7 @@ object Dependencies extends DependencyBuilders {
lazy val `scalajs-react-core` = Def.setting("com.github.japgolly.scalajs-react" %%% "core" % Versions.`scalajs-react`)
lazy val `scalajs-react-extra` = Def.setting("com.github.japgolly.scalajs-react" %%% "extra" % Versions.`scalajs-react`)
lazy val `scalajs-react-test` = Def.setting("com.github.japgolly.scalajs-react" %%% "test" % Versions.`scalajs-react`)
lazy val `scalacss-ext-react` = Def.setting("com.github.japgolly.scalacss" %%% "ext-react" % Versions.scalacss)

// Scala: JVM + JS libraries
lazy val scalatest = Def.setting("org.scalatest" %%% "scalatest" % Versions.scalatest)
Expand All @@ -42,7 +45,8 @@ object Dependencies extends DependencyBuilders {
// JavaScript: Node.js libraries
lazy val `semantic-ui-react`: NpmDependency = "semantic-ui-react" -> Versions.`semantic-ui-react`
lazy val `react-sortable-hoc`: NpmDependency = "react-sortable-hoc" -> Versions.`react-sortable-hoc`
lazy val `react-beautiful-dnd`: NpmDependency = "react-beautiful-dnd" -> Versions.`react-beautiful-dnd`
lazy val `react-trello`: NpmDependency = "react-trello" -> Versions.`react-trello`
lazy val react: NpmDependency = "react" -> Versions.react
lazy val `react-dom`: NpmDependency = "react-dom" -> Versions.react
lazy val `babel-runtime` = "@babel/runtime" -> Versions.`babel-runtime`
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.dbrsn.scalajs.react.trello

import com.dbrsn.scalajs.react.macros.tojs.JSMacro
import com.dbrsn.scalajs.react.trello.data._
import japgolly.scalajs.react.component.Js.{RawMounted, UnmountedWithRawType}
import japgolly.scalajs.react.raw.React.Element
import japgolly.scalajs.react.{Callback, Children, JsComponent}

import scala.scalajs.js

final case class Board[Metadata](
id: js.UndefOr[BoardId] = js.undefined,
actions: js.UndefOr[RawAction] = js.undefined,
data: Data[Metadata],
reducerData: js.UndefOr[Data[Metadata]] = js.undefined,
onDataChange: js.UndefOr[Data[Metadata] => Callback] = js.undefined,
eventBusHandle: js.UndefOr[js.Any => Callback] = js.undefined,
onLaneScroll: js.UndefOr[(Int, LaneId) => Callback] = js.undefined,
onCardClick: js.UndefOr[(CardId, Metadata, LaneId) => Callback] = js.undefined,
onCardDelete: js.UndefOr[(CardId, LaneId) => Callback] = js.undefined,
onCardAdd: js.UndefOr[(Card[Metadata], LaneId) => Callback] = js.undefined,
addCardLink: js.UndefOr[Element] = js.undefined,
onLaneClick: js.UndefOr[LaneId => Callback] = js.undefined,
laneSortFunction: js.UndefOr[(Card[Metadata], Card[Metadata]) => Callback] = js.undefined,
draggable: js.UndefOr[Boolean] = js.undefined,
collapsibleLanes: js.UndefOr[Boolean] = js.undefined,
editable: js.UndefOr[Boolean] = js.undefined,
hideCardDeleteIcon: js.UndefOr[Boolean] = js.undefined,
handleDragStart: js.UndefOr[(CardId, LaneId) => Callback] = js.undefined,
handleDragEnd: js.UndefOr[(CardId, SourceLaneId, TargetLaneId, Int) => Callback] = js.undefined,
handleLaneDragStart: js.UndefOr[LaneId => Callback] = js.undefined,
handleLaneDragEnd: js.UndefOr[(LaneId, Int) => Callback] = js.undefined,
customCardLayout: js.UndefOr[Boolean] = js.undefined,
customLaneHeader: js.UndefOr[Element] = js.undefined,
style: js.UndefOr[RawStyle] = js.undefined,
tagStyle: js.UndefOr[RawStyle] = js.undefined,
laneDraggable: js.UndefOr[Boolean] = js.undefined,
cardDraggable: js.UndefOr[Boolean] = js.undefined,
cardDragClass: js.UndefOr[String] = js.undefined,
laneDragClass: js.UndefOr[String] = js.undefined,
addLaneTitle: js.UndefOr[String] = js.undefined,
addCardTitle: js.UndefOr[String] = js.undefined,
newLaneTemplate: js.UndefOr[Element] = js.undefined,
className: js.UndefOr[String] = js.undefined
) {
def apply(): UnmountedWithRawType[js.Object, Null, RawMounted[js.Object, Null]] = {
val props = JSMacro[Board[Metadata]](this)
val f = JsComponent[js.Object, Children.None, Null](ReactTrello.Board)
f(props)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dbrsn.scalajs.react.trello

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

object ReactTrello {
@js.native @JSImport("react-trello/dist/components/Board", JSImport.Default)
object Board extends js.Any
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.dbrsn.scalajs.react.trello.data

import scalacss.internal.StyleS

import scala.scalajs.js
import scala.scalajs.js.UndefOr

@js.native
trait Card[Metadata] extends js.Object {
def id: CardId = js.native
def title: String = js.native
def label: String = js.native
def description: String = js.native
def cardStyle: UndefOr[RawStyle] = js.native
def metadata: UndefOr[Metadata] = js.native
}

object Card {
def apply[Metadata <: js.Any](
id: CardId,
title: String,
label: String = "",
description: String = "",
cardStyle: UndefOr[RawStyle] = js.undefined,
metadata: UndefOr[Metadata] = js.undefined
): Card[Metadata] =
js.Dynamic
.literal(
id = id,
title = title,
label = label,
description = description,
cardStyle = cardStyle,
metadata = metadata
)
.asInstanceOf[Card[Metadata]]

def styled[Metadata <: js.Any](
id: CardId,
title: String,
label: String = "",
description: String = "",
cardStyle: UndefOr[StyleS],
metadata: UndefOr[Metadata] = js.undefined
): Card[Metadata] = apply[Metadata](
id = id,
title = title,
label = label,
description = description,
cardStyle = cardStyle.map(_.toJsAny),
metadata = metadata
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dbrsn.scalajs.react.trello.data

import scala.scalajs.js
import scala.scalajs.js.JSConverters._

@js.native
trait Data[Metadata] extends js.Object {
def lanes: js.Array[Lane[Metadata]] = js.native
}

object Data {
def apply[Metadata](lanes: Lane[Metadata]*): Data[Metadata] =
js.Dynamic.literal(lanes = lanes.toJSArray).asInstanceOf[Data[Metadata]]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.dbrsn.scalajs.react.trello.data

import scalacss.internal.StyleS

import scala.scalajs.js
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.UndefOr

@js.native
trait Lane[Metadata] extends js.Object {
def id: LaneId = js.native
def title: String = js.native
def label: String = js.native
def style: UndefOr[RawStyle] = js.native
def cards: js.Array[Card[Metadata]] = js.native
def droppable: Boolean = js.native
}

object Lane {
def apply[Metadata](
id: LaneId,
title: String,
label: String = "",
style: UndefOr[RawStyle] = js.undefined,
droppable: Boolean = true
)(
cards: Card[Metadata]*
): Lane[Metadata] =
js.Dynamic
.literal(
id = id,
title = title,
label = label,
style = style,
droppable = droppable,
cards = cards.toJSArray
)
.asInstanceOf[Lane[Metadata]]

def styled[Metadata](
id: LaneId,
title: String,
label: String = "",
style: UndefOr[StyleS] = js.undefined,
droppable: Boolean = true
)(
cards: Card[Metadata]*
): Lane[Metadata] =
apply(
id = id,
title = title,
label = label,
style = style.map(_.toJsAny),
droppable = droppable
)(cards: _*)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.dbrsn.scalajs.react.trello

import com.dbrsn.scalajs.react.trello.data.Tag.@@
import scalacss.internal.StyleS

import scala.scalajs.js

package object data {
type RawAction = js.Any
type RawStyle = js.Any

object RawStyle {
def empty: RawStyle = new js.Object()
}

type BoardId = String @@ BoardId.Tag
type CardId = String @@ CardId.Tag
type LaneId = String @@ LaneId.Tag

type SourceLaneId = LaneId
type TargetLaneId = LaneId

final def styleS2JsAny(style: StyleS): js.Any = {
val result = js.Dictionary.empty[String]
style.data.values.flatMap(_.avIterator).foreach { property =>
// Map CSS property name to react style naming convention.
// For example: padding-top => paddingTop
val propertyName = property.attr.id.split("-") match {
case Array(head, other @ _*) => head + other.map(_.capitalize).mkString
}
result(propertyName) = property.value
}
result
}

implicit class StyleSOps(val style: StyleS) extends AnyVal {
def toJsAny: js.Any = styleS2JsAny(style)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.dbrsn.scalajs.react.trello.data

object Tag {
@inline def apply[U]: Tagger[U] = new Tagger[U]

trait Tagged[U]
type @@[+T, U] = T with Tagged[U]

class Tagger[U] {
@inline def apply[T](t: T): T @@ U = t.asInstanceOf[T @@ U]
}
}

object BoardId {
sealed trait Tag
@inline def apply(id: String): BoardId = Tag[Tag][String](id)
}

object CardId {
sealed trait Tag
@inline def apply(id: String): CardId = Tag[Tag][String](id)

}

object LaneId {
sealed trait Tag
@inline def apply(id: String): LaneId = Tag[Tag][String](id)
}
Loading

0 comments on commit 0ae257b

Please sign in to comment.