Permalink
Browse files

Initial implementation of web service support. Example in stack.mobl.

  • Loading branch information...
zefhemel committed Jun 23, 2010
1 parent 65fc72e commit 7f6d190f3965c6326e8ba053c5209a59ffee5c42
View
@@ -24,6 +24,13 @@
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
+ <inkscape:perspective
+ id="perspective2834"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
@@ -33,15 +40,15 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
- inkscape:cx="282.45658"
- inkscape:cy="759.37667"
+ inkscape:cx="256.69769"
+ inkscape:cy="718.97057"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1151"
inkscape:window-height="825"
- inkscape:window-x="20"
- inkscape:window-y="20"
+ inkscape:window-x="176"
+ inkscape:window-y="28"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
@@ -51,6 +58,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
@@ -65,24 +73,53 @@
y="362.31323"
id="text2816"
transform="scale(1.0325302,0.9684947)"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"><tspan
+ inkscape:export-xdpi="53.380001"
+ inkscape:export-ydpi="53.380001"
+ inkscape:export-filename="/Users/zef/git/mobl-docs/logo.png"><tspan
sodipodi:role="line"
x="81.44886"
y="362.31323"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Sans;-inkscape-font-specification:LucidaTypewriter Medium"
id="tspan2820"><tspan
- style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#447821;stroke:none;font-family:Sans;-inkscape-font-specification:LucidaTypewriter Medium"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#ac0e22;stroke:none;font-family:Sans;-inkscape-font-specification:LucidaTypewriter Medium;fill-opacity:1"
id="tspan3598">m</tspan>obl</tspan></text>
<rect
id="rect2824"
width="156.5461"
height="130.0304"
x="67.004616"
y="255.9447"
- style="fill:none;stroke:#447821;stroke-width:11.17391396000000015;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.94117647000000004;stroke-dasharray:none"
+ style="fill:none;stroke:#ac0e22;stroke-width:11.17391396000000015;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ transform="matrix(0.99807891,-0.06195554,0.05829475,0.99829942,0,0)"
+ inkscape:export-filename="/Users/zef/git/mobl-docs/logo.png"
+ inkscape:export-xdpi="53.380001"
+ inkscape:export-ydpi="53.380001" />
+ <text
+ xml:space="preserve"
+ style="font-size:148.03289795000000595px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#ac0e22;fill-opacity:1;stroke:none;font-family:Bodoni SvtyTwo OS ITC TT;-inkscape-font-specification:Bodoni SvtyTwo OS ITC TT"
+ x="215.40359"
+ y="551.62213"
+ id="text2816-7"
+ transform="scale(1.0325302,0.96849468)"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90"
+ inkscape:export-filename="/Users/zef/git/mobl/m.png"><tspan
+ sodipodi:role="line"
+ x="215.40359"
+ y="551.62213"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:Sans;-inkscape-font-specification:LucidaTypewriter Medium;fill:#ac0e22;fill-opacity:1"
+ id="tspan2820-9"><tspan
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#ac0e22;stroke:none;font-family:Sans;-inkscape-font-specification:LucidaTypewriter Medium;fill-opacity:1"
+ id="tspan3598-3">m</tspan></tspan></text>
+ <rect
+ id="rect2824-8"
+ width="156.5461"
+ height="130.0304"
+ x="194.39453"
+ y="447.50763"
+ style="fill:none;stroke:#ac0e22;stroke-width:11.17391396000000015;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
transform="matrix(0.99807891,-0.06195554,0.05829475,0.99829942,0,0)"
- inkscape:export-filename="/Users/zef/git/mobl/text2816.png"
+ inkscape:export-filename="/Users/zef/git/mobl/m.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90" />
</g>
View
@@ -0,0 +1,165 @@
+application stack
+
+import mobl
+
+screen root() {
+ init {
+ var questions = StackOverflow.questions(answers=true, body=true);
+ for(question in questions) {
+ add(question);
+ for(answer in question.answers) {
+ add(answer);
+ }
+ }
+ }
+}
+
+external type QuestionsResult {
+ total : Num
+ page : Num
+ pagesize : Num
+ questions : Array<Question>
+}
+
+// Stack overflow types
+external type RemoteQuestion {
+ question_id : Num
+ title : String
+ owner : RemoteUser
+ body : Text
+ tags : Array<String>
+ answers : Array<RemoteAnswer>
+ answer_count : Num
+ favorite_count : Num
+ question_id : Num
+ creation_date : Num
+ up_vote_count : Num
+ down_vote_count : Num
+ score : Num
+ view_count : Num
+}
+
+external type RemoteAnswer {
+ answer_id : Num
+ accepted : Bool
+ owner : RemoteUser
+ creation_date : Num
+ last_edit_date : Num
+ up_vote_count : Num
+ down_vote_count : Num
+ score : Num
+ body : Text
+}
+
+external type RemoteUser {
+ user_id : Num
+ display_name : String
+ reputation : Num
+}
+
+// Locally cached version
+
+entity Question {
+ questionId : Num
+ title : String
+ body : Text
+ answers : Collection<Answer> (inverse: question)
+ upVotes : Num
+ downVotes : Num
+ creationDate : DateTime
+ owner : User
+}
+
+entity Answer {
+ question : Question
+ answerId : Num
+ accepted : Bool
+ owner : User
+ created : DateTime
+ lastEdit : DateTime
+ score : Num
+ body : Text
+}
+
+entity User {
+ userId : Num
+ name : String
+ reputation : Num
+}
+
+function mapQuestion(remote : RemoteQuestion) : Question {
+ var q = Question.all().filter("questionId", "=", remote.question_id).one();
+ if(q == null) {
+ q = Question {
+ questionId = remote.question_id,
+ title = remote.title,
+ body = remote.body,
+ answers = mapAnswers(remote.answers),
+ upVotes = remote.up_vote_count,
+ downVotes = remote.down_vote_count,
+ creationDate = DateTime.fromTimestamp(remote.creation_date),
+ owner = mapUser(remote.owner)
+ };
+ add(q);
+ } else {
+ if(q.answers.count() != remote.answer_count) {
+ q.answers.destroyAll();
+ q.answers = mapAnswers(remote.answers);
+ }
+ }
+ return q;
+}
+
+function mapAnswers(answers : Array<RemoteAnswer>) : Collection<Answer> {
+ var resultList : Collection<Answer> = Collection<Answer>();
+ for(answer in answers) {
+ resultList.add(mapAnswer(answer));
+ }
+ return resultList;
+}
+
+function mapAnswer(answer : RemoteAnswer) : Answer {
+ return Answer{
+ answerId=answer.answer_id,
+ accepted=answer.accepted,
+ owner=mapUser(answer.owner),
+ created=DateTime.fromTimestamp(answer.creation_date),
+ lastEdit=DateTime.fromTimestamp(answer.last_edit_date),
+ score=answer.score,
+ body=answer.body
+ };
+}
+
+function mapUser(user : RemoteUser) : User {
+ log(user);
+ var u = User.all().filter("userId", "=", user.user_id).one();
+ if(u == null) {
+ u = User {
+ userId = user.user_id,
+ name = user.display_name,
+ reputation = user.reputation
+ };
+ add(u);
+ }
+ return u;
+}
+
+function mapQuestionsResult(res : QuestionsResult) : Collection<Question> {
+ log("Here's the data: ");
+ log(res);
+ var resultList : Collection<Question> = Collection<Question>();
+ for(question in res.questions) {
+ resultList.add(mapQuestion(question));
+ }
+ return resultList;
+}
+
+service StackOverflow {
+ root = "http://api.stackoverflow.com/0.8"
+ resource questions(answers : Bool = false, body : Bool = false) : Collection<Question> {
+ uri = "/questions"
+ method = "GET"
+ encoding = "json"
+ mapper = mapQuestionsResult
+ }
+}
View
@@ -23,6 +23,11 @@ external type List<T> {
sync function add(item : T) : void
}
+external type Array<T> {
+ sync function get(n : Num) : T
+ sync function push(item : T) : void
+}
+
external type Tuple1<T1> {
_1 : T1
}
@@ -64,6 +69,8 @@ external type Text : Object { }
external type DateTime {
static sync function parse(s : String) : DateTime
+ static sync function fromTimestamp(timestamp : Num) : DateTime
+
sync function getFullYear() : Num
sync function getMonth() : Num
@@ -94,9 +101,15 @@ external type Collection<T> {
@doc "Filter the collection on a property based on an operator `op` (options: '=', '<', '>', '<=', '>=' or '!=') and a value"
sync function filter(property : String, op : String, value : Object) : Collection<T>
- @doc "Order the collection based on a property in ascending (ascending = true) or dedescending (ascending = false) order"
+ @doc "Order the collection based on a property in ascending (ascending = true) or descending (ascending = false) order"
sync function order(property : String, ascending : Bool) : Collection<T>
+ @doc "Deletes all the items in the collection"
+ function destroyAll() : void
+
+ @doc "Count the number of items in the collection"
+ function count() : Num
+
sync function limit(n : Num) : Collection<T>
sync function offset(n : Num) : Collection<T>
sync function add(item : T) : void
@@ -163,6 +176,10 @@ control inputString(s : String, placeholder : String = null, onchange : Callback
</li>
}
+control textbox(s : String, placeholder : String = null, onchange : Callback = null) {
+ <input type="text" placeholder=placeholder databind=s onchange=onchange />
+}
+
control searchbox(s : String, placeholder : String = null, onsearch : Callback = null) {
<div class="searchbox">
<input type="text" placeholder=placeholder databind=s onchange=onsearch />
@@ -221,6 +238,7 @@ control basicView(title : String, toolBar : Control = control{}) {
</div>
}
+@doc "Renders a table, use row { } rows and cell { } for cells"
control table() {
<table>elements()</table>
}
@@ -390,6 +408,9 @@ persistence.QueryCollection.prototype.updates = function() {
mobl.DateTime = {
parse: function(s) {
return new Date(Date.parse(s));
+ },
+ fromTimestamp: function(timestamp) {
+ return new Date(timestamp);
}
};
@@ -430,4 +451,16 @@ persistence.entityDecoratorHooks.push(function(Entity) {
};
});
+Array.prototype.list = function(tx, callback) {
+ var valueCopy = [];
+ for(var i = 0; i < this.length; i++) {
+ valueCopy[i] = this[i];
+ }
+ callback(valueCopy);
+};
+
+Array.prototype.get = function(idx) {
+ return this[idx];
+};
+
</script>
View
@@ -5,6 +5,7 @@ imports
MoBL-UI
MoBL-Data
MoBL-Action
+ MoBL-Service
MoBL-External
exports
View
@@ -3,15 +3,14 @@ application tipcalculator
import mobl
screen root() {
- var amount : Num = 10
- var percentage : Num = 10
+ var amount = 10
+ var percentage = 10
var total <- amount * (1 + percentage/100)
- // formula total <- amount * (1 + percentage/100)
header("Tip calculator")
group {
- inputNum(amount, label="amount")
- inputNum(percentage, label="%")
+ item { inputNum(amount, label="amount") }
+ item { inputNum(percentage, label="%") }
item { label(total)}
}
}
Oops, something went wrong.

0 comments on commit 7f6d190

Please sign in to comment.