Commit 4da30bee authored by Laurent Wouters's avatar Laurent Wouters
Browse files

Adding new application framework

parent 742f86d2ee2f
......@@ -21,5 +21,8 @@ let make = _children => {
},
reducer: Framework.States.reduce,
didUpdate: oldNewSelf => Framework.States.on_updated(oldNewSelf),
render: self => Framework.Rendering.render(self.state),
render: self => {
let view = Framework.Rendering.get_view(self.state);
},
};
\ No newline at end of file
let renderLoading = (_state: Framework.appState) =>
let renderLoading =
(
self: ReasonReact.self(Framework.appState, _, Framework.appAction),
state: Framework.appState,
) =>
<div> (ReasonReact.string("Loading")) </div>;
let renderFailed = (_state: Framework.appState) =>
let renderFailed =
(
self: ReasonReact.self(Framework.appState, _, Framework.appAction),
state: Framework.appState,
) =>
<div> (ReasonReact.string("Failed")) </div>;
let renderRoot = (_state: Framework.appState) =>
<div> (ReasonReact.string("Root")) </div>;
let renderRoot =
(
self: ReasonReact.self(Framework.appState, _, Framework.appAction),
state: Framework.appState,
) => {
let resource = Framework.States.root_resource(state);
let schema = Hypermedia.Schema.as_root(Framework.schema_of(resource));
<div>
<h1> (ReasonReact.string(schema.title)) </h1>
(
schema.links
|> List.map((link: Hypermedia.schemaLink) => {
let link_href =
switch (link.href) {
| Some(x) => x
| None => ""
};
let title =
switch (link.title) {
| Some(x) => x
| None => ""
};
<li>
<a
href=link_href
onClick=(
self.handle((_event, _self) =>
Framework.follow_link(link_href)
)
)>
(ReasonReact.string(title))
</a>
</li>;
})
|> Array.of_list
|> ReasonReact.array
)
</div>;
};
let renderCollection = (_state: Framework.appState) =>
let renderCollection =
(
self: ReasonReact.self(Framework.appState, _, Framework.appAction),
state: Framework.appState,
) =>
<div> (ReasonReact.string("Collection")) </div>;
let renderEntity = (_state: Framework.appState) =>
let renderEntity =
(
self: ReasonReact.self(Framework.appState, _, Framework.appAction),
state: Framework.appState,
) =>
<div> (ReasonReact.string("Entity")) </div>;
let defaultRegistry =
let defaultRegistry = () : Framework.viewRegistry =>
Framework.Create.registry([
Framework.Create.view(
"::defaults::Loading",
"Default loading view",
Framework.LoadingView,
0,
renderLoading,
"::defaults::Loading",
"::defaults::Loading",
),
Framework.Create.view(
"::defaults::Failed",
"Default failed view",
Framework.FailedView,
0,
renderFailed,
"::defaults::Failed",
"::defaults::Failed",
),
Framework.Create.view(
"::defaults::Root",
"Default root view",
Framework.RootView,
0,
renderRoot,
"::defaults::Root",
"::defaults::Root",
),
Framework.Create.view(
"::defaults::Collection",
"Default collection view",
Framework.CollectionView(None),
0,
renderCollection,
"::defaults::Collection",
"::defaults::Collection",
),
Framework.Create.view(
"::defaults::Entity",
"Default entity view",
Framework.EntityView(None),
0,
renderEntity,
"::defaults::Entity",
"::defaults::Entity",
),
]);
\ No newline at end of file
......@@ -36,14 +36,16 @@ type viewKind =
(* A specification *)
type viewSpecification = {
(* The location and thus identifier of this view *)
location: string;
(* The unique identifier for this view *)
identifier: string;
(* The view's human readable name *)
name: string;
(* The kind of view *)
kind: viewKind;
(* The priority given to the view *)
priority: int;
(* The location where to load the view from *)
location: string;
}
(* A piece of fetched data *)
......@@ -74,17 +76,12 @@ let data_of resource = match resource.data with
| Some(data) -> data
(* Type of a rendering function *)
type viewRenderer =
appState
-> ReasonReact.reactElement
(* The definition of a view *)
and view = {
type view = {
(* The specification of this view *)
specification: viewSpecification;
(* The view rendering function *)
renderer: viewRenderer;
renderer: string;
}
(* A registry of views *)
......@@ -368,11 +365,52 @@ end = struct
end
(* Module for a React component *)
module type ComponentType = sig
(* Type of the Reason component *)
type t
(* Get the state of a component *)
val state : t -> appState
end
(* Module for rendering *)
module Rendering : sig
(* Renders an application state *)
val get_view: appState -> view
end = struct
module type RendererT = sig
(* Type of the Reason component *)
type self
(* Type of a rendering function *)
type viewRenderer =
self
-> appState
-> ReasonReact.reactElement
(* The type *)
type +'a t
(* Initializes a renderer *)
val empty : 'a t
(* Registers a view implementation *)
val register : string -> viewRenderer -> 'a t -> 'a t
(* Renders a component *)
val render : self -> 'a t -> ReasonReact.reactElement
end
(* Module for rendering *)
module Renderer(CT : ComponentType) = struct
(* Type of the Reason component *)
type self = CT.t
(* Type of a rendering function *)
type viewRenderer =
self
-> appState
-> ReasonReact.reactElement
(* The type *)
type 'a t = viewRenderer StringMap.t
(* Initializes a renderer *)
let empty = StringMap.empty
(* Select the view if it is appropriate for this kind *)
let best_of_1 (view: view) (kind: viewKind) = match view.specification.kind, kind with
| LoadingView, LoadingView
......@@ -434,25 +472,37 @@ end = struct
let get_view state = match do_get_view state with
| None -> raise (BadState "Could not find a view")
| Some(view) -> view
(* Registers a view implementation *)
let register identifier renderer registry =
StringMap.add identifier renderer registry
(* Renders a component *)
let render self registry =
let state = CT.state self in
let view = get_view state in
let renderer = StringMap.find view.renderer registry in
renderer self state
end
(* Module for creating views *)
module Create = struct
let view location name kind priority renderer = {
let view identifier name kind priority location renderer = {
specification = {
location = location;
identifier = identifier;
name = name;
kind = kind;
priority = priority;
location = location;
};
renderer = renderer;
}
(* Register a new view into a registry *)
let register_view (registry: viewRegistry) (view: view) = {
specifications = StringMap.add view.specification.location view.specification registry.specifications;
definitions = StringMap.add view.specification.location view registry.definitions;
specifications = StringMap.add view.specification.identifier view.specification registry.specifications;
definitions = StringMap.add view.specification.identifier view registry.definitions;
}
let registry (views: view list) =
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment