Simple form working end-to-end
This commit is contained in:
parent
edaa7a7ca5
commit
54e645f252
|
@ -1,46 +1 @@
|
||||||
'use strict';
|
/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
|
||||||
|
|
||||||
var $$Array = require("bs-platform/lib/js/array.js");
|
|
||||||
var Curry = require("bs-platform/lib/js/curry.js");
|
|
||||||
var React = require("react");
|
|
||||||
var Belt_Option = require("bs-platform/lib/js/belt_Option.js");
|
|
||||||
var Belt_MapString = require("bs-platform/lib/js/belt_MapString.js");
|
|
||||||
var Model$ProbExample = require("../Model.bs.js");
|
|
||||||
var EAFunds_Model$ProbExample = require("./EAFunds_Model.bs.js");
|
|
||||||
|
|
||||||
function handleChange(handleChange$1, $$event) {
|
|
||||||
return Curry._1(handleChange$1, $$event.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
var model = EAFunds_Model$ProbExample.Interface.model;
|
|
||||||
|
|
||||||
var initialMap = Model$ProbExample.toMaps(model);
|
|
||||||
|
|
||||||
function EAFunds_Form(Props) {
|
|
||||||
var match = React.useState((function () {
|
|
||||||
return Model$ProbExample.toMaps(model);
|
|
||||||
}));
|
|
||||||
var params = match[0];
|
|
||||||
return $$Array.map((function (parameter) {
|
|
||||||
var __x = Belt_MapString.get(params[/* inputs */1], parameter[/* id */0]);
|
|
||||||
var value = Belt_Option.flatMap(__x, (function (param) {
|
|
||||||
return param[1];
|
|
||||||
}));
|
|
||||||
return React.createElement(React.Fragment, undefined, parameter[/* name */1], parameter[/* id */0], React.createElement(Model$ProbExample.Input.Form.make, {
|
|
||||||
parameter: parameter,
|
|
||||||
value: value,
|
|
||||||
onChange: (function (r) {
|
|
||||||
console.log(r);
|
|
||||||
return /* () */0;
|
|
||||||
})
|
|
||||||
}));
|
|
||||||
}), $$Array.of_list(model[/* inputs */3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
var make = EAFunds_Form;
|
|
||||||
|
|
||||||
exports.handleChange = handleChange;
|
|
||||||
exports.model = model;
|
|
||||||
exports.initialMap = initialMap;
|
|
||||||
exports.make = make;
|
|
||||||
/* initialMap Not a pure module */
|
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
let model = EAFunds_Model.Interface.model;
|
// let model = EAFunds_Model.Interface.model;
|
||||||
|
// let handleChange = (handleChange, event) =>
|
||||||
let handleChange = (handleChange, event) =>
|
// handleChange(ReactEvent.Form.target(event)##value);
|
||||||
handleChange(ReactEvent.Form.target(event)##value);
|
// let model = EAFunds_Model.Interface.model;
|
||||||
|
// let initialMap = Model.toMaps(model);
|
||||||
let model = EAFunds_Model.Interface.model;
|
// [@react.component]
|
||||||
let initialMap = Model.toMaps(model);
|
// let make = () => {
|
||||||
|
// let (params, changeParams) = React.useState(() => Model.toMaps(model));
|
||||||
[@react.component]
|
// model.inputs
|
||||||
let make = () => {
|
// |> Array.of_list
|
||||||
let (params, changeParams) = React.useState(() => Model.toMaps(model));
|
// |> Array.map((parameter: Model.Input.parameter) => {
|
||||||
model.inputs
|
// let value =
|
||||||
|> Array.of_list
|
// params.inputs->Model.MS.get(parameter.id)
|
||||||
|> Array.map((parameter: Model.Input.parameter) => {
|
// |> Belt.Option.flatMap(_, ((_, b)) => b);
|
||||||
let value =
|
// <>
|
||||||
params.inputs->Model.MS.get(parameter.id)
|
// {parameter.name |> ReasonReact.string}
|
||||||
|> Belt.Option.flatMap(_, ((_, b)) => b);
|
// {parameter.id |> ReasonReact.string}
|
||||||
<>
|
// <Model.Input.Form parameter value onChange={r => Js.log(r)} />
|
||||||
{parameter.name |> ReasonReact.string}
|
// </>;
|
||||||
{parameter.id |> ReasonReact.string}
|
// });
|
||||||
<Model.Input.Form parameter value onChange={r => Js.log(r)} />
|
/* }*/
|
||||||
</>;
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,52 +1,50 @@
|
||||||
open EAFunds_Data;
|
// open EAFunds_Data;
|
||||||
|
// let handleChange = (handleChange, event) =>
|
||||||
let handleChange = (handleChange, event) =>
|
// handleChange(ReactEvent.Form.target(event)##value);
|
||||||
handleChange(ReactEvent.Form.target(event)##value);
|
// [@react.component]
|
||||||
|
// let make = () => {
|
||||||
[@react.component]
|
// let (year, setYear) = React.useState(() => 2021.);
|
||||||
let make = () => {
|
// <>
|
||||||
let (year, setYear) = React.useState(() => 2021.);
|
// <h1> {"EA Funds Forecasting Model 0.1" |> ReasonReact.string} </h1>
|
||||||
<>
|
// <input
|
||||||
<h1> {"EA Funds Forecasting Model 0.1" |> ReasonReact.string} </h1>
|
// type_="number"
|
||||||
<input
|
// value={year |> Js.Float.toString}
|
||||||
type_="number"
|
// onChange={handleChange(r =>
|
||||||
value={year |> Js.Float.toString}
|
// switch (Js.Float.fromString(r)) {
|
||||||
onChange={handleChange(r =>
|
// | r when r >= 2020.0 && r <= 2050.0 => setYear(_ => r)
|
||||||
switch (Js.Float.fromString(r)) {
|
// | _ => ()
|
||||||
| r when r >= 2020.0 && r <= 2050.0 => setYear(_ => r)
|
// }
|
||||||
| _ => ()
|
// )}
|
||||||
}
|
// />
|
||||||
)}
|
// <table className="table-auto">
|
||||||
/>
|
// <thead>
|
||||||
<table className="table-auto">
|
// <tr>
|
||||||
<thead>
|
// <th className="px-4 py-2"> {"Fund Name" |> ReasonReact.string} </th>
|
||||||
<tr>
|
// <th className="px-4 py-2"> {"Donations" |> ReasonReact.string} </th>
|
||||||
<th className="px-4 py-2"> {"Fund Name" |> ReasonReact.string} </th>
|
// <th className="px-4 py-2"> {"Payouts" |> ReasonReact.string} </th>
|
||||||
<th className="px-4 py-2"> {"Donations" |> ReasonReact.string} </th>
|
// </tr>
|
||||||
<th className="px-4 py-2"> {"Payouts" |> ReasonReact.string} </th>
|
// </thead>
|
||||||
</tr>
|
// <tbody>
|
||||||
</thead>
|
// {funds
|
||||||
<tbody>
|
// |> Belt.Array.map(_, r =>
|
||||||
{funds
|
// <tr>
|
||||||
|> Belt.Array.map(_, r =>
|
// <th className="px-4 py-2 border ">
|
||||||
<tr>
|
// {r.name |> ReasonReact.string}
|
||||||
<th className="px-4 py-2 border ">
|
// </th>
|
||||||
{r.name |> ReasonReact.string}
|
// <th className="px-4 py-2 border font-normal">
|
||||||
</th>
|
// {EAFunds_Model.go(r.group, year, DONATIONS)
|
||||||
<th className="px-4 py-2 border font-normal">
|
// |> Model.InputTypes.to_string
|
||||||
{EAFunds_Model.go(r.group, year, DONATIONS)
|
// |> ReasonReact.string}
|
||||||
|> Model.InputTypes.to_string
|
// </th>
|
||||||
|> ReasonReact.string}
|
// <th className="px-4 py-2 border font-normal">
|
||||||
</th>
|
// {EAFunds_Model.go(r.group, year, PAYOUTS)
|
||||||
<th className="px-4 py-2 border font-normal">
|
// |> Model.InputTypes.to_string
|
||||||
{EAFunds_Model.go(r.group, year, PAYOUTS)
|
// |> ReasonReact.string}
|
||||||
|> Model.InputTypes.to_string
|
// </th>
|
||||||
|> ReasonReact.string}
|
// </tr>
|
||||||
</th>
|
// )
|
||||||
</tr>
|
// |> ReasonReact.array}
|
||||||
)
|
// </tbody>
|
||||||
|> ReasonReact.array}
|
// </table>
|
||||||
</tbody>
|
// </>;
|
||||||
</table>
|
/* }*/
|
||||||
</>;
|
|
||||||
};
|
|
|
@ -1,8 +1,10 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Block = require("bs-platform/lib/js/block.js");
|
var Block = require("bs-platform/lib/js/block.js");
|
||||||
|
var Curry = require("bs-platform/lib/js/curry.js");
|
||||||
|
var React = require("react");
|
||||||
var Math$ProbExample = require("../Math.bs.js");
|
var Math$ProbExample = require("../Math.bs.js");
|
||||||
var Model$ProbExample = require("../Model.bs.js");
|
var Prop$ProbExample = require("../Prop.bs.js");
|
||||||
|
|
||||||
function yearDiff(year) {
|
function yearDiff(year) {
|
||||||
return year - 2020.0;
|
return year - 2020.0;
|
||||||
|
@ -66,46 +68,38 @@ var PayoutsIfAround = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function go(group, year, output) {
|
function go(group, year, output) {
|
||||||
return /* FloatCdf */Block.__(3, [calculateDifference(currentValue(group, output), year, /* record */[
|
return /* FloatCdf */Block.__(2, [calculateDifference(currentValue(group, output), year, /* record */[
|
||||||
/* meanDiff */1.1,
|
/* meanDiff */1.1,
|
||||||
/* stdDiff */1.1
|
/* stdDiff */1.1
|
||||||
])]);
|
])]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var model_002 = /* assumptions : :: */[
|
var model_002 = /* inputTypes : array */[
|
||||||
Model$ProbExample.Input.make("Yearly Growth Rate", /* FloatPoint */0, undefined, /* () */0),
|
Prop$ProbExample.TypeWithMetadata.make("Fund", /* SelectSingle */Block.__(0, [/* record */[
|
||||||
/* :: */[
|
|
||||||
Model$ProbExample.Input.currentYear,
|
|
||||||
/* [] */0
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
var model_003 = /* inputs : :: */[
|
|
||||||
Model$ProbExample.Input.make("Fund", /* SingleChoice */Block.__(1, [/* record */[
|
|
||||||
/* options : :: */[
|
/* options : :: */[
|
||||||
/* tuple */[
|
/* record */[
|
||||||
"Animal Welfare Fund",
|
/* id */"animal",
|
||||||
"animal"
|
/* name */"Animal Welfare Fund"
|
||||||
],
|
],
|
||||||
/* :: */[
|
/* :: */[
|
||||||
/* tuple */[
|
/* record */[
|
||||||
"Global Health Fund",
|
/* id */"globalHealth",
|
||||||
"globalHealth"
|
/* name */"Global Health Fund"
|
||||||
],
|
],
|
||||||
/* :: */[
|
/* :: */[
|
||||||
/* tuple */[
|
/* record */[
|
||||||
"Long Term Future Fund",
|
/* id */"longTerm",
|
||||||
"longTerm"
|
/* name */"Long Term Future Fund"
|
||||||
],
|
],
|
||||||
/* :: */[
|
/* :: */[
|
||||||
/* tuple */[
|
/* record */[
|
||||||
"Meta Fund",
|
/* id */"longterm",
|
||||||
"meta"
|
/* name */"Meta Fund"
|
||||||
],
|
],
|
||||||
/* :: */[
|
/* :: */[
|
||||||
/* tuple */[
|
/* record */[
|
||||||
"All",
|
/* id */"all",
|
||||||
"all"
|
/* name */"All"
|
||||||
],
|
],
|
||||||
/* [] */0
|
/* [] */0
|
||||||
]
|
]
|
||||||
|
@ -114,32 +108,21 @@ var model_003 = /* inputs : :: */[
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
/* default */"total"
|
/* default */"total"
|
||||||
]]), undefined, /* () */0),
|
]]), undefined, undefined, undefined, /* () */0),
|
||||||
/* :: */[
|
Prop$ProbExample.TypeWithMetadata.make("Year", /* Year */Block.__(2, [/* record */[
|
||||||
Model$ProbExample.Input.make("Year", /* Year */Block.__(0, [/* record */[
|
|
||||||
/* default */2030.0,
|
/* default */2030.0,
|
||||||
/* min */2020.0,
|
/* min */2020.0,
|
||||||
/* max */2050.0
|
/* max */2050.0
|
||||||
]]), undefined, /* () */0),
|
]]), undefined, undefined, undefined, /* () */0)
|
||||||
/* [] */0
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
var model_004 = /* outputs : :: */[
|
var model_003 = /* outputTypes : array */[];
|
||||||
Model$ProbExample.Output.make("Payments", /* FloatCdf */2, undefined, /* () */0),
|
|
||||||
/* :: */[
|
|
||||||
Model$ProbExample.Output.make("Payouts", /* FloatCdf */2, undefined, /* () */0),
|
|
||||||
/* [] */0
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
var model = /* record */[
|
var model = /* record */[
|
||||||
/* name */"Calculate the payments and payouts of EA Funds based on existing data.",
|
/* name */"Calculate the payments and payouts of EA Funds based on existing data.",
|
||||||
/* author */"George Harrison",
|
/* author */"George Harrison",
|
||||||
model_002,
|
model_002,
|
||||||
model_003,
|
model_003
|
||||||
model_004,
|
|
||||||
/* outputConfig : Single */0
|
|
||||||
];
|
];
|
||||||
|
|
||||||
function convertChoice(s) {
|
function convertChoice(s) {
|
||||||
|
@ -158,48 +141,54 @@ function convertChoice(s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(p) {
|
function run(p) {
|
||||||
var match = p[/* assumptions */0];
|
var partial_arg = p[/* inputValues */1];
|
||||||
var match$1 = p[/* inputs */1];
|
var partial_arg$1 = Prop$ProbExample.ValueMap.get;
|
||||||
if (match) {
|
var get = function (param) {
|
||||||
var match$2 = match[0];
|
return partial_arg$1(partial_arg, param);
|
||||||
if (match$2 !== undefined) {
|
};
|
||||||
var match$3 = match$2;
|
var match = Curry._1(get, "Fund");
|
||||||
if (match$3.tag) {
|
var match$1 = Curry._1(get, "Year");
|
||||||
return ;
|
if (match !== undefined) {
|
||||||
} else {
|
var match$2 = match;
|
||||||
var match$4 = match[1];
|
switch (match$2.tag | 0) {
|
||||||
if (match$4) {
|
case /* SelectSingle */0 :
|
||||||
var match$5 = match$4[0];
|
if (match$1 !== undefined) {
|
||||||
if (match$5 !== undefined && !(match$5.tag || match$4[1] || !match$1)) {
|
var match$3 = match$1;
|
||||||
var match$6 = match$1[0];
|
switch (match$3.tag | 0) {
|
||||||
if (match$6 !== undefined) {
|
case /* FloatPoint */1 :
|
||||||
var match$7 = match$6;
|
return go(convertChoice(match$2[0]), match$3[0], /* DONATIONS */0);
|
||||||
if (match$7.tag === /* SingleChoice */1 && !match$1[1]) {
|
case /* SelectSingle */0 :
|
||||||
return go(convertChoice(match$7[0]), match$3[0], /* DONATIONS */0);
|
case /* FloatCdf */2 :
|
||||||
} else {
|
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
} else {
|
case /* FloatPoint */1 :
|
||||||
return ;
|
case /* FloatCdf */2 :
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function EAFunds_Model$Interface$Form(Props) {
|
||||||
|
return React.createElement(Prop$ProbExample.ModelForm.make, {
|
||||||
|
combo: Prop$ProbExample.Combo.fromModel(model)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var Form = {
|
||||||
|
make: EAFunds_Model$Interface$Form
|
||||||
|
};
|
||||||
|
|
||||||
var Interface = {
|
var Interface = {
|
||||||
model: model,
|
model: model,
|
||||||
convertChoice: convertChoice,
|
convertChoice: convertChoice,
|
||||||
run: run
|
run: run,
|
||||||
|
Form: Form
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.PayoutsIfAround = PayoutsIfAround;
|
exports.PayoutsIfAround = PayoutsIfAround;
|
||||||
|
|
|
@ -44,7 +44,7 @@ module PayoutsIfAround = {
|
||||||
|
|
||||||
let go = (group: group, year: float, output: output) => {
|
let go = (group: group, year: float, output: output) => {
|
||||||
PayoutsIfAround.(
|
PayoutsIfAround.(
|
||||||
Model.InputTypes.FloatCdf(
|
Prop.Value.FloatCdf(
|
||||||
calculateDifference(
|
calculateDifference(
|
||||||
currentValue(group, output),
|
currentValue(group, output),
|
||||||
year,
|
year,
|
||||||
|
@ -55,34 +55,30 @@ let go = (group: group, year: float, output: output) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module Interface = {
|
module Interface = {
|
||||||
open Model;
|
open Prop;
|
||||||
|
|
||||||
let model = {
|
let model: Model.t = {
|
||||||
name: "Calculate the payments and payouts of EA Funds based on existing data.",
|
name: "Calculate the payments and payouts of EA Funds based on existing data.",
|
||||||
author: "George Harrison",
|
author: "George Harrison",
|
||||||
assumptions: [
|
inputTypes: [|
|
||||||
Input.make(~name="Yearly Growth Rate", ~parameterType=FloatPoint, ()),
|
TypeWithMetadata.make(
|
||||||
Input.currentYear,
|
|
||||||
],
|
|
||||||
inputs: [
|
|
||||||
Input.make(
|
|
||||||
~name="Fund",
|
~name="Fund",
|
||||||
~parameterType=
|
~type_=
|
||||||
SingleChoice({
|
SelectSingle({
|
||||||
default: Some("total"),
|
default: Some("total"),
|
||||||
options: [
|
options: [
|
||||||
("Animal Welfare Fund", "animal"),
|
{name: "Animal Welfare Fund", id: "animal"},
|
||||||
("Global Health Fund", "globalHealth"),
|
{name: "Global Health Fund", id: "globalHealth"},
|
||||||
("Long Term Future Fund", "longTerm"),
|
{name: "Long Term Future Fund", id: "longTerm"},
|
||||||
("Meta Fund", "meta"),
|
{name: "Meta Fund", id: "longterm"},
|
||||||
("All", "all"),
|
{name: "All", id: "all"},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
(),
|
(),
|
||||||
),
|
),
|
||||||
Input.make(
|
TypeWithMetadata.make(
|
||||||
~name="Year",
|
~name="Year",
|
||||||
~parameterType=
|
~type_=
|
||||||
Year({
|
Year({
|
||||||
default: Some(2030.0),
|
default: Some(2030.0),
|
||||||
min: Some(2020.0),
|
min: Some(2020.0),
|
||||||
|
@ -90,12 +86,8 @@ module Interface = {
|
||||||
}),
|
}),
|
||||||
(),
|
(),
|
||||||
),
|
),
|
||||||
],
|
|],
|
||||||
outputs: [
|
outputTypes: [||],
|
||||||
Output.make(~name="Payments", ~parameterType=FloatCdf, ()),
|
|
||||||
Output.make(~name="Payouts", ~parameterType=FloatCdf, ()),
|
|
||||||
],
|
|
||||||
outputConfig: Single,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let convertChoice = (s: string) =>
|
let convertChoice = (s: string) =>
|
||||||
|
@ -107,14 +99,17 @@ module Interface = {
|
||||||
| _ => All
|
| _ => All
|
||||||
};
|
};
|
||||||
|
|
||||||
let run = (p: Model.modelParams) => {
|
let run = (p: Combo.t) => {
|
||||||
switch (p.assumptions, p.inputs) {
|
let get = Prop.ValueMap.get(p.inputValues);
|
||||||
| (
|
switch (get("Fund"), get("Year")) {
|
||||||
[Some(Year(intendedYear)), Some(Year(currentYear))],
|
| (Some(SelectSingle(fund)), Some(FloatPoint(intendedYear))) =>
|
||||||
[Some(SingleChoice(fund))],
|
|
||||||
) =>
|
|
||||||
Some(go(convertChoice(fund), intendedYear, DONATIONS))
|
Some(go(convertChoice(fund), intendedYear, DONATIONS))
|
||||||
| _ => None
|
| _ => None
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module Form = {
|
||||||
|
[@react.component]
|
||||||
|
let make = () => <Prop.ModelForm combo={Prop.Combo.fromModel(model)} />;
|
||||||
|
};
|
||||||
};
|
};
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
var React = require("react");
|
var React = require("react");
|
||||||
var ReactDOMRe = require("reason-react/src/ReactDOMRe.js");
|
var ReactDOMRe = require("reason-react/src/ReactDOMRe.js");
|
||||||
var EAFunds_Form2$ProbExample = require("./EAFunds/EAFunds_Form2.bs.js");
|
var EAFunds_Model$ProbExample = require("./EAFunds/EAFunds_Model.bs.js");
|
||||||
|
|
||||||
((import('./styles/index.css')));
|
((import('./styles/index.css')));
|
||||||
|
|
||||||
ReactDOMRe.renderToElementWithId(React.createElement(EAFunds_Form2$ProbExample.make, { }), "app");
|
ReactDOMRe.renderToElementWithId(React.createElement(EAFunds_Model$ProbExample.Interface.Form.make, { }), "app");
|
||||||
|
|
||||||
/* Not a pure module */
|
/* Not a pure module */
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
[%bs.raw {|import('./styles/index.css')|}];
|
[%bs.raw {|import('./styles/index.css')|}];
|
||||||
ReactDOMRe.renderToElementWithId(<EAFunds_Form2 />, "app");
|
ReactDOMRe.renderToElementWithId(<EAFunds_Model.Interface.Form />, "app");
|
|
@ -1,17 +0,0 @@
|
||||||
type yearAsFloat = {
|
|
||||||
min: option(float),
|
|
||||||
max: option(float),
|
|
||||||
};
|
|
||||||
|
|
||||||
type namedValue('a) = {
|
|
||||||
name: string,
|
|
||||||
value: 'a,
|
|
||||||
};
|
|
||||||
|
|
||||||
type choice('a) = list(namedValue('a));
|
|
||||||
|
|
||||||
type output =
|
|
||||||
| A
|
|
||||||
| B;
|
|
||||||
|
|
||||||
let nOutput: choice(output) = [{name: "sdfsdf", value: A}];
|
|
92
src/Prop.re
92
src/Prop.re
|
@ -51,12 +51,12 @@ module Type = {
|
||||||
module ValueMap = {
|
module ValueMap = {
|
||||||
module MS = Belt.Map.String;
|
module MS = Belt.Map.String;
|
||||||
type t = MS.t(Value.t);
|
type t = MS.t(Value.t);
|
||||||
let get = MS.get;
|
let get = (t: t, s) => MS.get(t, s);
|
||||||
let keys = MS.keysToArray;
|
let keys = MS.keysToArray;
|
||||||
let map = MS.map;
|
let map = MS.map;
|
||||||
let fromArray = (r): t => MS.fromArray(r);
|
let fromArray = (r): t => MS.fromArray(r);
|
||||||
let values = (t: t) => t |> MS.valuesToArray;
|
let values = (t: t) => t |> MS.valuesToArray;
|
||||||
let update = MS.update;
|
let update = (t, k, v) => MS.update(t, k, _ => v);
|
||||||
let toArray = MS.toArray;
|
let toArray = MS.toArray;
|
||||||
let fromOptionalMap = (t: MS.t(option(Value.t))): t =>
|
let fromOptionalMap = (t: MS.t(option(Value.t))): t =>
|
||||||
MS.keep(t, (_, d) => E.O.isSome(d))
|
MS.keep(t, (_, d) => E.O.isSome(d))
|
||||||
|
@ -121,7 +121,7 @@ module Model = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module Combo = {
|
module Combo = {
|
||||||
type combo = {
|
type t = {
|
||||||
model: Model.t,
|
model: Model.t,
|
||||||
inputValues: ValueMap.t,
|
inputValues: ValueMap.t,
|
||||||
outputValues: ValueMap.t,
|
outputValues: ValueMap.t,
|
||||||
|
@ -135,20 +135,90 @@ module Combo = {
|
||||||
)
|
)
|
||||||
|> ValueMap.fromOptionalArray;
|
|> ValueMap.fromOptionalArray;
|
||||||
|
|
||||||
let isValid = (t: combo) =>
|
let isValid = t =>
|
||||||
t.model
|
t.model
|
||||||
|> Model.InputTypes.keys
|
|> Model.InputTypes.keys
|
||||||
|> E.A.fmap(ValueMap.get(t.inputValues))
|
|> E.A.fmap(ValueMap.get(t.inputValues))
|
||||||
|> Belt.Array.some(_, E.O.isNone);
|
|> Belt.Array.some(_, E.O.isNone);
|
||||||
|
|
||||||
let update =
|
let update = (t, key: string, onUpdate: option(Value.t)) =>
|
||||||
(
|
|
||||||
t: combo,
|
|
||||||
key: string,
|
|
||||||
onUpdate: option(Value.t) => option(Value.t),
|
|
||||||
) =>
|
|
||||||
ValueMap.update(t.inputValues, key, onUpdate);
|
ValueMap.update(t.inputValues, key, onUpdate);
|
||||||
};
|
};
|
||||||
|
|
||||||
let run = (t: combo, f): ValueMap.t => f(t.inputValues);
|
let updateInputValue = (t, k, u) => {
|
||||||
|
...t,
|
||||||
|
inputValues: InputValues.update(t, k, u),
|
||||||
|
};
|
||||||
|
|
||||||
|
let inputTypeValuePairs = (t: t) =>
|
||||||
|
t.model.inputTypes
|
||||||
|
|> E.A.fmap((i: TypeWithMetadata.t) =>
|
||||||
|
(i, ValueMap.get(t.inputValues, i.id))
|
||||||
|
);
|
||||||
|
|
||||||
|
let fromModel = (t: Model.t) => {
|
||||||
|
model: t,
|
||||||
|
inputValues: InputValues.defaults(t),
|
||||||
|
outputValues: InputValues.defaults(t),
|
||||||
|
};
|
||||||
|
|
||||||
|
let run = (t: t, f): ValueMap.t => f(t.inputValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
module ValueForm = {
|
||||||
|
let handleChange = (handleChange, event) =>
|
||||||
|
handleChange(ReactEvent.Form.target(event)##value);
|
||||||
|
type onChange = option(Value.t) => unit;
|
||||||
|
|
||||||
|
[@react.component]
|
||||||
|
let make =
|
||||||
|
(
|
||||||
|
~type_: TypeWithMetadata.t,
|
||||||
|
~value: option(Value.t),
|
||||||
|
~onChange: onChange,
|
||||||
|
) => {
|
||||||
|
switch (type_.type_, value) {
|
||||||
|
| (Year(_), Some(FloatPoint(r))) =>
|
||||||
|
<input
|
||||||
|
type_="number"
|
||||||
|
value={r |> Js.Float.toString}
|
||||||
|
onChange={handleChange(r =>
|
||||||
|
switch (Js.Float.fromString(r)) {
|
||||||
|
| r => onChange(Some(Value.FloatPoint(r)))
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
| (FloatPoint(_), Some(FloatPoint(r))) =>
|
||||||
|
<input type_="number" value={r |> Js.Float.toString} />
|
||||||
|
| (Year(_), _)
|
||||||
|
| (FloatPoint(_), _) => <input type_="number" value="" />
|
||||||
|
| (SelectSingle(_), _) =>
|
||||||
|
<div> {"Single Choice" |> ReasonReact.string} </div>
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module ModelForm = {
|
||||||
|
let handleChange = (handleChange, event) =>
|
||||||
|
handleChange(ReactEvent.Form.target(event)##value);
|
||||||
|
|
||||||
|
[@react.component]
|
||||||
|
let make = (~combo: Combo.t) => {
|
||||||
|
let (combo, setCombo) = React.useState(() => combo);
|
||||||
|
<div>
|
||||||
|
{Combo.inputTypeValuePairs(combo)
|
||||||
|
|> E.A.fmap(((type_, value)) =>
|
||||||
|
<ValueForm
|
||||||
|
type_
|
||||||
|
value
|
||||||
|
onChange={newValue =>
|
||||||
|
setCombo(_ =>
|
||||||
|
Combo.updateInputValue(combo, type_.id, newValue)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|> ReasonReact.array}
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user