Skip to content

Instantly share code, notes, and snippets.

@felher
Created May 2, 2020 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save felher/ef9d31ec05ee376f4e645e52771d4ae9 to your computer and use it in GitHub Desktop.
Save felher/ef9d31ec05ee376f4e645e52771d4ae9 to your computer and use it in GitHub Desktop.
import io.circe.generic.extras.ConfiguredJsonCodec
import io.circe.parser._
import scala.scalajs.js
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
@ConfiguredJsonCodec
sealed trait Node {}
@JSExportTopLevel("TextQuestion")
@JSExportAll
final case class TextQuestion(id: String, value: Option[String]) extends Node
@JSExportTopLevel("Group")
@JSExportAll
final case class Group(id: String, parts: List[Node]) extends Node
object Node {
@JSExportTopLevel("unsafeParse")
def unsafeParse(s: String): Node =
decode[Node](s) match {
case Left(t) => throw t
case Right(n) => n
}
@JSExportTopLevel("orDefault")
def orDefault[A](o: Option[A], default: A): A =
o.getOrElse(default)
@JSExportTopLevel("dispatch")
def dispatch[A](
node: Node,
ofGroup: js.Function1[Group, A],
ofTextQuestion: js.Function1[TextQuestion, A],
): A = node match {
case x: TextQuestion => ofTextQuestion(x)
case x: Group => ofGroup(x)
}
@JSExportTopLevel("toArray")
def toArray[A](l: List[A]): js.Array[A] = l.toJSArray
}
export declare module './ecrf' {
export class Option<X> {}
export class List<X> {}
export type Node = TextQuestion | Group
export class TextQuestion {
id: string;
value: Option<string>;
}
export class Group {
id: string;
parts: List<Node>;
}
export function orDefault<X>(o: Option<X>, def: X): X
export function dispatch<A>(n: Node, ofGroup: (g: Group) => A, ofTextQuestion: (t: TextQuestion) => A): A
export function unsafeParse(s: string): Node
export function toArray<A>(l: List<A>): A[]
}
import React, {ReactElement} from 'react';
import * as E from "./ecrf";
export const EcrfTest = (props: {}): ReactElement => {
return <div>
<GroupC group={tree as E.Group}/>
</div>;
}
export const GroupC = (props: {group: E.Group}): ReactElement => {
return <div className="group-node">
<div>{props.group.id}</div>
<div className="children">
{
E.toArray(props.group.parts).map((n: E.Node, i: number) =>
E.dispatch(n,
(g: any) => <GroupC key={i} group={g}/>,
(t: any) => <TextQuestionC key={i} question={t}/>)
)
}
</div>
</div>
}
export const TextQuestionC = (props: {question: E.TextQuestion}): ReactElement => {
return <div className="question-node">
<div>{props.question.id}</div>
<div>{E.orDefault(props.question.value, "default")}</div>
</div>
}
export const tree = E.unsafeParse(`
{
"kind": "Group",
"id": "Group1",
"parts": [
{
"kind": "Group",
"id": "Group11",
"parts": [
{
"kind": "TextQuestion",
"id": "TQ111",
"value": "hey value"
}
]
},
{
"kind": "Group",
"id": "Group12",
"parts": [
{
"kind": "TextQuestion",
"id": "TQ121",
"value": "hey value2"
},
{
"kind": "TextQuestion",
"id": "TQ122"
}
]
}
]
}
`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment