Skip to content

Commit

Permalink
Improve facades apply (#26)
Browse files Browse the repository at this point in the history
* Add apply method to facades

* Update components to apply

* Remove redundant children

* Minor changes
  • Loading branch information
KapStorm authored Sep 28, 2023
1 parent 9057e3c commit 313fc83
Show file tree
Hide file tree
Showing 27 changed files with 206 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,16 @@ object AdminView {
def buildResources: Seq[ReactElement] = {
tables.map { table =>
Resource(
Resource.Props(
name = table.name,
list = ListGuesser(table),
edit = EditGuesser(table, props.dataExplorerSettings),
create = CreateGuesser(table)
)
name = table.name,
list = ListGuesser(table),
edit = EditGuesser(table, props.dataExplorerSettings),
create = CreateGuesser(table)
).withKey(table.name)
}
}

div()(
Admin(Admin.Props(dataProvider = simpleRestProvider(tablesUrl), children = buildResources)),
Admin(simpleRestProvider(tablesUrl))(buildResources),
error.map(h1(_))
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,38 +23,29 @@ object CreateGuesser {

field.`type` match {
case ColumnType.Date =>
DateTimeInput(DateTimeInput.Props(source = field.name, isRequired = isRequired, validate = required))
DateTimeInput(source = field.name, isRequired = isRequired, validate = required)
case ColumnType.Text =>
TextInput(TextInput.Props(source = field.name, isRequired = isRequired, validate = required))
TextInput(source = field.name, isRequired = isRequired, validate = required)
case ColumnType.Email =>
TextInput(TextInput.Props(source = field.name, isRequired = isRequired, validate = required))
TextInput(source = field.name, isRequired = isRequired, validate = required)
case ColumnType.Image =>
ImageField(ImageField.Props(source = field.name, isRequired = isRequired, validate = required))
ImageField(source = field.name, isRequired = isRequired, validate = required)
case ColumnType.Number =>
NumberInput(NumberInput.Props(source = field.name, isRequired = isRequired, validate = required))
NumberInput(source = field.name, isRequired = isRequired, validate = required)
case ColumnType.Reference(reference, source) =>
ReferenceInput(
ReferenceInput.Props(
source = field.name,
reference = reference,
children = Seq(
SelectInput(SelectInput.Props(optionText = source, isRequired = isRequired, validate = required))
),
isRequired = isRequired,
validate = required
)
)
source = field.name,
reference = reference,
isRequired = isRequired,
validate = required
)(SelectInput(optionText = source, isRequired = isRequired, validate = required))
}
}
.getOrElse(Fragment())
}

Create(
Create.Props(
SimpleForm(
SimpleForm.Props(toolbar = Fragment(), children = inputs :+ SaveButton())
)
)
SimpleForm(Fragment())(inputs.appended(SaveButton()): _*)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,16 @@ object EditGuesser {
if !field.isVisible then Fragment()
else
field.`type` match {
case ColumnType.Date => DateTimeInput(DateTimeInput.Props(source = field.name, disabled = field.disabled))
case ColumnType.Text => TextInput(TextInput.Props(source = field.name, disabled = field.disabled))
case ColumnType.Email => TextInput(TextInput.Props(source = field.name, disabled = field.disabled))
case ColumnType.Image => ImageField(ImageField.Props(source = field.name))
case ColumnType.Number => NumberInput(NumberInput.Props(source = field.name, disabled = field.disabled))
case ColumnType.Date => DateTimeInput(source = field.name, disabled = field.disabled)
case ColumnType.Text => TextInput(source = field.name, disabled = field.disabled)
case ColumnType.Email => TextInput(source = field.name, disabled = field.disabled)
case ColumnType.Image => ImageField(source = field.name)
case ColumnType.Number => NumberInput(source = field.name, disabled = field.disabled)
case ColumnType.Reference(reference, source) =>
ReferenceInput(
ReferenceInput.Props(
source = field.name,
reference = reference,
children = Seq(SelectInput(SelectInput.Props(optionText = source, disabled = field.disabled)))
)
)
source = field.name,
reference = reference
)(SelectInput(optionText = source, disabled = field.disabled))
}
}

Expand All @@ -65,29 +62,22 @@ object EditGuesser {
tableAction
.map { x =>
x.actions.map { action =>
Button(Button.Props(onClick = () => onClick(action, ctx), children = Seq(action.text)))
Button(onClick = () => onClick(action, ctx))(action.text)
}: Seq[ReactElement]
}
.getOrElse(Seq.empty)
}

val actions = TopToolbar(TopToolbar.Props(children = buttons()))
val actions = TopToolbar(buttons())

val deleteButton: ReactElement = if (props.response.canBeDeleted) DeleteButton() else Fragment()
val toolbar: ReactElement = Toolbar(
Toolbar.Props(children =
Seq(
SaveButton(),
deleteButton
)
)
SaveButton(),
deleteButton
)

Edit(
Edit.Props(
actions = actions(),
children = Seq(SimpleForm(SimpleForm.Props(toolbar = toolbar, children = inputs)))
)
Edit(actions)(
SimpleForm(toolbar)(inputs)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,57 +20,45 @@ object ListGuesser {
val component: FunctionalComponent[Props] = FunctionalComponent[Props] { props =>
val fields = ResponseGuesser.getTypesFromResponse(props.response)

def defaultField(reference: String, source: String, children: Seq[ReactElement]): ReactElement =
ReferenceField(
ReferenceField.Props(
reference = reference,
source = source,
children = children
)
)
def defaultField(reference: String, source: String)(children: ReactElement*): ReactElement =
ReferenceField(reference = reference, source = source)(children)

val widgetFields: Seq[ReactElement] = fields.map { field =>
if !field.isVisible then Fragment()
else {
val imageStyles = js.Dynamic.literal("width" -> "100px")
val styles = js.Dynamic.literal("& img" -> imageStyles)
field.`type` match {
case Date => DateField(DateField.Props(source = field.name, showTime = true))
case Text => TextField(TextField.Props(source = field.name))
case Email => EmailField(EmailField.Props(source = field.name))
case Image => ImageField(ImageField.Props(source = field.name, sx = styles))
case Number => NumberField(NumberField.Props(source = field.name))
case Date => DateField(source = field.name, showTime = true)
case Text => TextField(source = field.name)
case Email => EmailField(source = field.name)
case Image => ImageField(source = field.name, sx = styles)
case Number => NumberField(source = field.name)
case ColumnType.Reference(reference, source) =>
defaultField(reference, field.name, Seq(TextField(TextField.Props(source = source))))
defaultField(reference, field.name)(TextField(source = source))
}
}
}

val filterList: Seq[ReactElement] = fields.filter(_.filterable).map { field =>
field.`type` match {
case ColumnType.Date => DateInput(DateInput.Props(source = field.name))
case ColumnType.Text | ColumnType.Email => TextInput(TextInput.Props(source = field.name))
case ColumnType.Date => DateInput(source = field.name)
case ColumnType.Text | ColumnType.Email => TextInput(source = field.name)
case ColumnType.Image => Fragment()
case ColumnType.Number => NumberInput(NumberInput.Props(source = field.name))
case ColumnType.Number => NumberInput(source = field.name)
case ColumnType.Reference(reference, source) =>
defaultField(reference, field.name, Seq(TextField(TextField.Props(source = source))))
defaultField(reference, field.name)(TextField(source = source))
}
}

val listToolbar: ReactElement = TopToolbar(
TopToolbar.Props(
children = Seq(
FilterButton(FilterButton.Props(filters = filterList)),
ExportButton(),
CreateButton()
)
)
FilterButton(filters = filterList),
ExportButton(),
CreateButton()
)

ComponentList(ComponentList.Props(actions = listToolbar, filters = filterList))(
Datagrid(
Datagrid.Props(rowClick = "edit", bulkActionButtons = props.response.canBeDeleted, children = widgetFields)
)
ComponentList(listToolbar)(filterList: _*)(
Datagrid(rowClick = "edit", bulkActionButtons = props.response.canBeDeleted)(widgetFields)
)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import net.wiringbits.spra.ui.web.facades.DataProvider
import slinky.core.ExternalComponent
import slinky.core.facade.ReactElement
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|

object Admin extends ExternalComponent {
case class Props(dataProvider: DataProvider, children: Seq[ReactElement])
case class Props(dataProvider: DataProvider)

def apply(dataProvider: DataProvider): BuildingComponent[_, _] = {
super.apply(Props(dataProvider))
}

override val component: String | js.Object = ReactAdmin.Admin
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.facade.ReactElement
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|

object Button extends ExternalComponent {
case class Props(onClick: () => Unit, children: Seq[ReactElement])
case class Props(onClick: () => Unit)

def apply(onClick: () => Unit): BuildingComponent[_, _] = {
super.apply(Props(onClick))
}

override val component: String | js.Object = ReactAdmin.Button
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.facade.ReactElement
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|

object ComponentList extends ExternalComponent {
case class Props(actions: ReactElement, filters: Seq[ReactElement])

def apply(actions: ReactElement)(filters: ReactElement*): BuildingComponent[_, _] = {
super.apply(Props(actions, filters))
}

override val component: String | js.Object = ReactAdmin.List
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.facade.ReactElement
import slinky.core.ExternalComponentNoProps

import scala.scalajs.js

object Create extends ExternalComponent {
case class Props(children: ReactElement*)

object Create extends ExternalComponentNoProps {
override val component: String | js.Object = ReactAdmin.Create
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.facade.ReactElement
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|

object Datagrid extends ExternalComponent {
case class Props(rowClick: String, bulkActionButtons: Boolean, children: Seq[ReactElement])
case class Props(rowClick: String, bulkActionButtons: Boolean)

def apply(rowClick: String, bulkActionButtons: Boolean): BuildingComponent[_, _] =
super.apply(Props(rowClick, bulkActionButtons))

override val component: String | js.Object = ReactAdmin.Datagrid
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|

object DateField extends ExternalComponent {
case class Props(source: String, showTime: Boolean)

def apply(source: String, showTime: Boolean = false): BuildingComponent[_, _] = {
super.apply(Props(source, showTime))
}

override val component: String | js.Object = ReactAdmin.DateField
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|

object DateInput extends ExternalComponent {
case class Props(source: String, isRequired: Boolean = false, validate: js.UndefOr[js.Any] = js.undefined)

def apply(
source: String,
isRequired: Boolean = false,
validate: js.UndefOr[js.Any] = js.undefined
): BuildingComponent[_, _] = {
super.apply(Props(source, isRequired, validate))
}

override val component: String | js.Object = ReactAdmin.DateInput
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|
Expand All @@ -12,5 +12,13 @@ object DateTimeInput extends ExternalComponent {
isRequired: Boolean = false,
validate: js.UndefOr[js.Any] = js.undefined
)

def apply(
source: String,
disabled: Boolean = false,
isRequired: Boolean = false,
validate: js.UndefOr[js.Any] = js.undefined
): BuildingComponent[_, _] = super.apply(Props(source, disabled, isRequired, validate))

override val component: String | js.Object = ReactAdmin.DateTimeInput
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package net.wiringbits.spra.ui.web.facades.reactadmin

import slinky.core.ExternalComponent
import slinky.core.facade.ReactElement
import slinky.core.{BuildingComponent, ExternalComponent}

import scala.scalajs.js
import scala.scalajs.js.|

object Edit extends ExternalComponent {
case class Props(actions: ReactElement, children: Seq[ReactElement])
case class Props(actions: ReactElement)

def apply(actions: ReactElement): BuildingComponent[_, _] = {
super.apply(Props(actions))
}

override val component: String | js.Object = ReactAdmin.Edit
}
Loading

0 comments on commit 313fc83

Please sign in to comment.