Permalink
Browse files

Initial code for manual tutorials on web services.

  • Loading branch information...
akoprow committed Dec 2, 2011
0 parents commit 76cf43dc3e971713648d1525dd06be90bd341cea
@@ -0,0 +1,92 @@
+import stdlib.tools.markdown
+
+database stringmap(string) /wiki
+database /wiki[_] = "This page is empty. Double click to edit"
+
+exposed function load_source(topic) {
+ /wiki[topic]
+}
+
+exposed function load_rendered(topic) {
+ source = load_source(topic)
+ Markdown.xhtml_of_string(Markdown.default_options, source)
+}
+
+exposed function save_source(topic, source) {
+ /wiki[topic] <- source
+ load_rendered(topic)
+}
+
+exposed function remove_topic(topic) {
+ Db.remove(@/wiki[topic])
+}
+
+function edit(topic) {
+ Dom.set_value(#edit_content, load_source(topic))
+ Dom.hide(#show_content)
+ Dom.show(#edit_content)
+ Dom.give_focus(#edit_content)
+}
+
+function save(topic) {
+ content = save_source(topic, Dom.get_value(#edit_content))
+ #show_content = content
+ Dom.hide(#edit_content)
+ Dom.show(#show_content)
+}
+
+function display(topic) {
+ Resource.styled_page("About {topic}", ["/resources/css.css"],
+ <div id=#header><div id=#logo></div>About {topic}</div>
+ <div class="show_content" id=#show_content ondblclick={function(_) { edit(topic) }}>
+ {load_rendered(topic)}
+ </>
+ <textarea class="edit_content" id=#edit_content style="display:none"
+ cols="40" rows="30" onblur={function(_) { save(topic) }}></>
+ )
+}
+
+function rest(topic) {
+ match (HttpRequest.get_method()) {
+ case {some: method} :
+ match (method) {
+ case {post}: {
+ _ = save_source(topic, HttpRequest.get_body() ? "")
+ Resource.raw_status({success})
+ }
+ case {delete}: {
+ remove_topic(topic)
+ Resource.raw_status({success})
+ }
+ case {get}: {
+ Resource.raw_response(load_source(topic), "text/plain", {success})
+ }
+// FIXME to be replaced by default
+ case _: {
+ Resource.raw_status({method_not_allowed})
+ }
+ }
+ case _: {
+ Resource.raw_status({bad_request})
+ }
+ }
+}
+
+function topic_of_path(path) {
+ String.capitalize(String.to_lower(List.to_string_using("", "", "::", path)))
+}
+
+function start(url) {
+ match (url) {
+ case {path: [] ... }: {display("Hello")}
+ case {path: ["_rest_" | path] ...}: {rest(topic_of_path(path))}
+ case {~path ...}: {display(topic_of_path(path))}
+ }
+}
+
+Server.start(Server.http,
+ [ {bundle: @static_include_directory("resources")}
+ , {filter: Server.Filter.anywhere, dispatch: start}
+ ]
+)
+
@@ -0,0 +1,122 @@
+import stdlib.tools.markdown
+
+function uri_for_topic(topic) {
+ Uri.of_absolute(
+ {Uri.default_absolute with
+ schema : {some: "http"},
+ domain : "localhost",
+ port : {some: 8080},
+ path : ["_rest_", topic]
+ }
+ )
+}
+
+exposed function load_source(topic) {
+ match (WebClient.Get.try_get(uri_for_topic(topic))) {
+ case {failure: _} : { "Error, could not connect" }
+ case {~success} : {
+ match (WebClient.Result.get_class(success)) {
+ case {success}: { success.content }
+ case _: { "Error {success.code}" }
+ }
+ }
+ }
+}
+
+exposed function load_rendered(topic) {
+ source = load_source(topic)
+ Markdown.xhtml_of_string(Markdown.default_options, source)
+}
+
+exposed function save_source(topic, source) {
+ match (WebClient.Post.try_post(uri_for_topic(topic), source)) {
+ case { failure: _ }: {
+ {failure: "Could not reach the distant server"}
+ }
+ case { success: s }: {
+ match (WebClient.Result.get_class(s)) {
+ case {success}: {success: load_rendered(topic)}
+ case _: {failure: "Error {s.code}"}
+ }
+ }
+ }
+}
+
+function remove_topic(topic) {
+ _ = WebClient.Delete.try_delete(uri_for_topic(topic))
+ void
+}
+
+function edit(topic) {
+ #show_messages = <></>
+ Dom.set_value(#edit_content, load_source(topic))
+ Dom.hide(#show_content)
+ Dom.show(#edit_content)
+ Dom.give_focus(#edit_content)
+}
+
+function save(topic) {
+ match (save_source(topic, Dom.get_value(#edit_content))) {
+ case { ~success }: {
+ #show_content = success
+ Dom.hide(#edit_content)
+ Dom.show(#show_content)
+ }
+ case {~failure}: {
+ #show_messages = <>{failure}</>
+ }
+ }
+}
+
+function display(topic) {
+ Resource.styled_page("About {topic}", ["/resources/css.css"],
+ <div id=#header><div id=#logo></div>About {topic}</div>
+ <div class="show_content" id=#show_content ondblclick={function(_) { edit(topic) }}>{load_rendered(topic)}</>
+ <div class="show_messages" id=#show_messages />
+ <textarea class="edit_content" id=#edit_content style="display:none" cols="40" rows="30" onblur={function(_) { save(topic) }}></>
+ )
+}
+
+function rest(topic) {
+ match (HttpRequest.get_method()) {
+ case {some: method}: {
+ match (method) {
+ case {post}: {
+ _ = save_source(topic, HttpRequest.get_body()?"")
+ Resource.raw_status({success})
+ }
+ case {delete}: {
+ remove_topic(topic)
+ Resource.raw_status({success})
+ }
+ case {get}: {
+ Resource.source(load_source(topic), "text/plain")
+ }
+ case _: {
+ Resource.raw_status({method_not_allowed})
+ }
+ }
+ }
+ case _: {
+ Resource.raw_status({bad_request})
+ }
+ }
+}
+
+function topic_of_path(path) {
+ String.capitalize(String.to_lower(List.to_string_using("", "", "::", path)))
+}
+
+function start(url) {
+ match (url) {
+ case {path: [] ... }: { display("Hello") }
+ case {path: ["rest" | path] ...}: { rest(topic_of_path(path)) }
+ case {~path ...}: { display(topic_of_path(path)) }
+ }
+}
+
+Server.start(Server.http,
+ [ {bundle: @static_include_directory("resources")}
+ , {filter: Server.Filter.anywhere, dispatch: start}
+ ]
+)
@@ -0,0 +1,148 @@
+import stdlib.tools.markdown
+
+uri_for_topic =
+ domain_parser =
+ {CommandLine.default_parser with
+ names: ["--wiki-server-domain"],
+ description: "The REST server for this wiki. By default, localhost.",
+// FIXME, | after parser should not be needed
+ function on_param(x) { parser | y=Rule.consume -> {no_params: {x with domain: y}} }
+ }
+ port_parser =
+ {CommandLine.default_parser with
+ names: ["--wiki-server-port"],
+ description: "The server port of the REST server for this wiki. By default, 8080.",
+ function on_param(x) { parser | y=Rule.natural -> {no_params: {x with port: {some: y}}} }
+ }
+ base_uri =
+ CommandLine.filter(
+ {title : "Wiki arguments",
+ init : {Uri.default_absolute with domain: "localhost", schema: {some: "http"}},
+ parsers : [domain_parser, port_parser],
+ anonymous : []
+ }
+ )
+ function(topic) {
+ Uri.of_absolute({base_uri with path: ["_rest_", topic]})
+ }
+
+function uri_for_topic(topic) {
+ Uri.of_absolute(
+ {Uri.default_absolute with
+ schema : {some: "http"},
+ domain : "localhost",
+ port : {some: 8080},
+ path : ["_rest_", topic]
+ }
+ )
+}
+
+exposed function load_source(topic) {
+ match (WebClient.Get.try_get(uri_for_topic(topic))) {
+ case {failure: _} : { "Error, could not connect" }
+ case {~success} : {
+ match (WebClient.Result.get_class(success)) {
+ case {success}: { success.content }
+ case _: { "Error {success.code}" }
+ }
+ }
+ }
+}
+
+exposed function load_rendered(topic) {
+ source = load_source(topic)
+ Markdown.xhtml_of_string(Markdown.default_options, source)
+}
+
+exposed function save_source(topic, source) {
+ match (WebClient.Post.try_post(uri_for_topic(topic), source)) {
+ case { failure: _ }: {
+ {failure: "Could not reach the distant server"}
+ }
+ case { success: s }: {
+ match (WebClient.Result.get_class(s)) {
+ case {success}: {success: load_rendered(topic)}
+ case _: {failure: "Error {s.code}"}
+ }
+ }
+ }
+}
+
+function remove_topic(topic) {
+ _ = WebClient.Delete.try_delete(uri_for_topic(topic))
+ void
+}
+
+function edit(topic) {
+ #show_messages = <></>
+ Dom.set_value(#edit_content, load_source(topic))
+ Dom.hide(#show_content)
+ Dom.show(#edit_content)
+ Dom.give_focus(#edit_content)
+}
+
+function save(topic) {
+ match (save_source(topic, Dom.get_value(#edit_content))) {
+ case { ~success }: {
+ #show_content = success
+ Dom.hide(#edit_content)
+ Dom.show(#show_content)
+ }
+ case {~failure}: {
+ #show_messages = <>{failure}</>
+ }
+ }
+}
+
+function display(topic) {
+ Resource.styled_page("About {topic}", ["/resources/css.css"],
+ <div id=#header><div id=#logo></div>About {topic}</div>
+ <div class="show_content" id=#show_content ondblclick={function(_) { edit(topic) }}>{load_rendered(topic)}</>
+ <div class="show_messages" id=#show_messages />
+ <textarea class="edit_content" id=#edit_content style="display:none" cols="40" rows="30" onblur={function(_) { save(topic) }}></>
+ )
+}
+
+function rest(topic) {
+ match (HttpRequest.get_method()) {
+ case {some: method}: {
+ match (method) {
+ case {post}: {
+ _ = save_source(topic, HttpRequest.get_body()?"")
+ Resource.raw_status({success})
+ }
+ case {delete}: {
+ remove_topic(topic)
+ Resource.raw_status({success})
+ }
+ case {get}: {
+ Resource.source(load_source(topic), "text/plain")
+ }
+ case _: {
+ Resource.raw_status({method_not_allowed})
+ }
+ }
+ }
+ case _: {
+ Resource.raw_status({bad_request})
+ }
+ }
+}
+
+function topic_of_path(path) {
+ String.capitalize(String.to_lower(List.to_string_using("", "", "::", path)))
+}
+
+function start(url) {
+ match (url) {
+ case {path: [] ... }: { display("Hello") }
+ case {path: ["rest" | path] ...}: { rest(topic_of_path(path)) }
+ case {~path ...}: { display(topic_of_path(path)) }
+ }
+}
+
+Server.start(Server.http,
+ [ {bundle: @static_include_directory("resources")}
+ , {filter: Server.Filter.anywhere, dispatch: start}
+ ]
+)
@@ -0,0 +1,13 @@
+/***Header***/
+#logo {
+ background: url("/resources/opa-logo.png") no-repeat scroll 0 0 transparent;
+ height: 32px;
+ margin: 10px 0 5px;
+ width: 61px;
+}
+/***Editing area***/
+.content {margin-top:60px;}
+#edit_content {
+ width:100%;
+ display: none; /* initially hidden */
+}
Binary file not shown.

0 comments on commit 76cf43d

Please sign in to comment.