Commit 3a2f8347c150a3605ef627fba9c20c5e7a6d31e8

Many changes

  - now the app sweets to sweet store
  - also displays related web annotations on the web view
  • Diff rendering mode:
  • inline
  • side by side

.gitignore

1*.png1*.png
2*.*~2*.*~
3*.xml3*.xml
4conf.py

conf.py.sample

1SWEET_STORE_URL = 'your sweet store url here'

server.py

13import json13import json
14import urllib14import urllib
1515
16import conf
17import sweetmaker
18
16app = Flask(__name__)19app = Flask(__name__)
1720
21SWEET_STORE_URL = conf.SWEET_STORE_URL
1822
23
19@app.route('/', methods=['GET'])24@app.route('/', methods=['GET'])
20def index():25def index():
21 if request.args.has_key('url'):26 if request.args.has_key('url'):
65 ret = {}65 ret = {}
66 keywords_dict = json.loads(request.args['data'])66 keywords_dict = json.loads(request.args['data'])
67 #keywords = json.loads(keywords_dict)['data']67 #keywords = json.loads(keywords_dict)['data']
68 for i in collection.find():
69 for keyword in keywords_dict:
68 if 'nodes' in keywords_dict:
69 for i in collection.find():
70 try:70 try:
71 if keyword in i['nodes']:
72 del(i['_id'])
73 ret[y] = i
74 y = y + 1
71 if 'how' in i:
72 i['nodes'] = i['how']
75 except:73 except:
76 pass74 pass
75 for node in keywords_dict['nodes']:
76 try:
77 if node in i['nodes']:
78 del(i['_id'])
79 ret[y] = i
80 y = y + 1
81 except:
82 pass
83 elif 'where' in keywords_dict:
84 for i in collection.find({'uri': keywords_dict['where']}):
85 del(i['_id'])
86 ret[y] = i
87 y = y + 1
88 for i in collection.find({'where': {'$regex':\
89 keywords_dict['where']}}):
90 del(i['_id'])
91 ret[y] = i
92 y = y + 1
93
77 return render_template('blank.html', content = ret)94 return render_template('blank.html', content = ret)
7895
7996
103 try:103 try:
104 for i in requestData:104 for i in requestData:
105 coll.insert(i)105 coll.insert(i)
106 print 'inserted'
107 print requestData
106 response = make_response()108 response = make_response()
107 response.headers['Access-Control-Allow-Origin'] = '*'109 response.headers['Access-Control-Allow-Origin'] = '*'
108 response.status = '200 OK'
109 response.status_code = 200110 response.status_code = 200
110 return response
111 for i in requestData:
112 del(i['_id'])
113 i['how'] = '{concepts: ' + ', '.join(i['how']) + '}'
114 #i['how'] = attribs
115 print 'payload for sweet'
116 print requestData
117 sweetmaker.sweet(SWEET_STORE_URL, requestData)
111 except:118 except:
112 response = make_response()119 response = make_response()
113 response.status = "500"
120 response.status_code = 500
114 response.data = "Your post could not be saved. Try posting again."121 response.data = "Your post could not be saved. Try posting again."
115 return response
116122
123 return response
124
125
117@app.route('/web/', methods=['GET'])126@app.route('/web/', methods=['GET'])
118def web():127def web():
119 return render_template('web.html')128 return render_template('web.html')
147147
148 # inject the JS toolbar to annotate text148 # inject the JS toolbar to annotate text
149 jq = root.makeelement('script')149 jq = root.makeelement('script')
150 jq.set('src', 'static/jquery-1.9.1.min.js')
150 jq.set('src', '/static/jquery-1.9.1.min.js')
151151
152 script = root.makeelement('script')152 script = root.makeelement('script')
153 script.set('src', 'static/text-annotation.js')
153 script.set('src', '/static/text-annotation.js')
154154
155 tree = root.makeelement('script')155 tree = root.makeelement('script')
156 tree.set('src', 'static/tree.js')
156 tree.set('src', '/static/tree.js')
157157
158 bs_js = root.makeelement('script')158 bs_js = root.makeelement('script')
159 bs_js.set('src', 'static/bootstrap.js')
159 bs_js.set('src', '/static/bootstrap.js')
160160
161 jit = root.makeelement('script')161 jit = root.makeelement('script')
162 jit.set('src', 'static/jit.js')
162 jit.set('src', '/static/jit.js')
163163
164 us = root.makeelement('script')164 us = root.makeelement('script')
165 us.set('src', 'static/underscore-min-1.4.4.js')
165 us.set('src', '/static/underscore-min-1.4.4.js')
166166
167 link = root.makeelement('link')167 link = root.makeelement('link')
168 link.set('href', 'static/text-annotation.css')
168 link.set('href', '/static/text-annotation.css')
169 link.set('type', 'text/css')169 link.set('type', 'text/css')
170 link.set('rel', 'stylesheet')170 link.set('rel', 'stylesheet')
171171
172 bs = root.makeelement('link')172 bs = root.makeelement('link')
173 bs.set('href', 'static/bootstrap.css')
173 bs.set('href', '/static/bootstrap.css')
174 bs.set('type', 'text/css')174 bs.set('type', 'text/css')
175 bs.set('rel', 'stylesheet')175 bs.set('rel', 'stylesheet')
176176
177 tree_css = root.makeelement('link')177 tree_css = root.makeelement('link')
178 tree_css.set('href', 'static/tree.css')
178 tree_css.set('href', '/static/tree.css')
179 tree_css.set('type', 'text/css')179 tree_css.set('type', 'text/css')
180 tree_css.set('rel', 'stylesheet')180 tree_css.set('rel', 'stylesheet')
181181

static/myVector.js

77 "test",77 "test",
78 feature.geometry.getBounds().getCenterLonLat(),78 feature.geometry.getBounds().getCenterLonLat(),
79 new OpenLayers.Size(640,480),79 new OpenLayers.Size(640,480),
80 '<iframe src='+config.indexer+"/search?data="+JSON.stringify(ans.ans[i]["nodes"])+" ></iframe>",null,true);
80 '<iframe src='+config.indexer+"/search?data="+JSON.stringify({'nodes': ans.ans[i]["nodes"]})+" ></iframe>",null,true);
81 feature.popup = z;81 feature.popup = z;
82 z.panMapIfOutOfView = true;82 z.panMapIfOutOfView = true;
83 map.addPopup(z);83 map.addPopup(z);

static/text-annotation.js

35 //$(document).mouseover(onHover);35 //$(document).mouseover(onHover);
36 //$(document).mouseout(onHoverOut);36 //$(document).mouseout(onHoverOut);
37 };37 };
38 window.listAnno = function() { // list annotations of current page
39 console.log('listing annotations');
40 $.get(config.indexer + '/search?data=' +
41 JSON.stringify({'where': window.location.search.split('url=')[1]}),
42 function(data) {
43 //console.log(data);
44 $('#list-anno .modal-body').html(data);
45 $('#list-anno').modal();
46 });
47 };
48
38 var removeSelect = function() {49 var removeSelect = function() {
39 var nodes = document.getElementsByTagName('*');50 var nodes = document.getElementsByTagName('*');
40 var bar = document.getElementById('annotate-bar');51 var bar = document.getElementById('annotate-bar');
67 '<li><a></a></li>'+67 '<li><a></a></li>'+
68 '<li><button class="btn" id="anno-btn" onclick="initSelect();">Annotate</button></li>' +68 '<li><button class="btn" id="anno-btn" onclick="initSelect();">Annotate</button></li>' +
69 '<li><a></a></li>'+69 '<li><a></a></li>'+
70 '<li><button class="btn" id="list-anno-btn" onclick="listAnno();">Annotations</button></li>' +
71 '<li><a></a></li>'+
70 '<li><button class="btn" id="publish">Publish</button></li>' +72 '<li><button class="btn" id="publish">Publish</button></li>' +
71 '</ul></div></div>' +73 '</ul></div></div>' +
72 '<div id="sweeted"></div> <div id="posted"></div> <div id="fail-posting"></div>';
74 '<div id="sweeted"></div> <div id="posted"></div> <div id="fail-posting"></div>'+
75 '<div id="list-anno" class="modal hide fade" role="dialog" aria-labelledby="list-anno-label" aria-hidden="true">'+
76 ' <div class="modal-header">'+
77 ' <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>'+
78 ' <h3>Annotations</h3>'+
79 ' </div>'+
80 ' <div class="modal-body">'+
81 ' </div>'+
82 ' <div class="modal-footer">'+
83 ' <a href="#" class="btn" data-dismiss="modal" aria-hidden="true">Close</a>'+
84 ' </div>'+
85 '</div>';
73 };86 };
7487
75 var modal_template = function() {88 var modal_template = function() {

static/tree.js

162 window.location.href;162 window.location.href;
163 resource = decodeURIComponent(resource).replace('"', '', 'gi');163 resource = decodeURIComponent(resource).replace('"', '', 'gi');
164 var data = {164 var data = {
165 user: user,
166 type: this.type,
167 uri: resource,
168 nodes: this.nodes,
165 who: user,
166 what: this.type,
167 where: resource,
168 how: this.nodes,
169 name: attribs.name169 name: attribs.name
170 };170 };
171 if(attribs.hasOwnProperty('top') &&171 if(attribs.hasOwnProperty('top') &&
172 attribs.hasOwnProperty('bottom') &&172 attribs.hasOwnProperty('bottom') &&
173 attribs.hasOwnProperty('right') &&173 attribs.hasOwnProperty('right') &&
174 attribs.hasOwnProperty('left')) {174 attribs.hasOwnProperty('left')) {
175 data.top = attribs.top;
176 data.bottom = attribs.bottom;
177 data.left = attribs.left;
178 data.right = attribs.right;
175
176 data.where += '#[' + attribs.top +
177 ',' + attribs.bottom +
178 ',' + attribs.left +
179 ',' + attribs.right + ']';
179 }180 }
180 if(attribs.hasOwnProperty('xpath')) {181 if(attribs.hasOwnProperty('xpath')) {
181 data.xpath = attribs.xpath;
182 data.where += '#' + attribs.xpath;
182 }183 }
183 this.swts.push(data);184 this.swts.push(data);
184 this.nodes = [];185 this.nodes = [];
194 url: config.indexer + '/submit',194 url: config.indexer + '/submit',
195 data: {'data': JSON.stringify(this.swts)},195 data: {'data': JSON.stringify(this.swts)},
196 success: function() {196 success: function() {
197 /*$.ajax({
198 type: 'POST',
199 url: config.postTweetUrl,
200 data: {'data': JSON.stringify(this.swts)},
201 success: function() {
202 $('#posted').show();
203 this.swts = [];
204 },
205 error: function() {
206 $('#fail-posting').show();
207 }
208 });*/
209 //$('#posted').html(posted_template());
210 //$('#posted').show();
211 var swts = '';197 var swts = '';
212 for(var i in sweet.swts) {198 for(var i in sweet.swts) {
213 var data = sweet.swts[i];199 var data = sweet.swts[i];
214 console.log(data);200 console.log(data);
215 var swt = '@'+data.user+' '+data.type+' '+data.uri;
216 if(data.hasOwnProperty('xpath')) {
217 swt += ' xpath: '+data.xpath;
218 }
219 if(data.hasOwnProperty('top')) {
220 swt += ' #['+data.top+','+data.right+','+data.bottom+','+data.left+']';
221 }
222 swt += ' ' + data.nodes.join();
201 var swt = '@'+data.who+' #'+data.what+' / '+data.where;
202 swt += ' {' + data.how.join() + ' }';
223 swts += swt + '\n';203 swts += swt + '\n';
224 }204 }
225 console.log(swts);205 console.log(swts);

sweetmaker.py

1# SwtMaker
2# -------
3# Server-side component to make sweets and post them to specified
4# sweet store
5#
6# License: BSD, see LICENSE for more details.
7# Servelots 2013
8# Authors:
9# Arvind Khadri <arvind@servelots.com>
10# Anon Ray <rayanon@servelots.com>
11
12import requests
13import json
14from datetime import datetime
15
16TIMESTAMP_FORMAT = '%d-%m-%Y %H:%M:%S'
17
18def sweet(sweet_url, sweet_list):
19 sweets = makeSweet(sweet_list)
20 if not sweets:
21 return False
22 else:
23 request = requests.api.post(sweet_url, {'data': json.dumps(sweets)})
24 if request.status_code == 200:
25 return True
26 else:
27 return False
28
29def makeSweet(sweet_list):
30 for sweet in sweet_list:
31 if len(sweet['who']) and len(sweet['what']) and len(sweet['where'])\
32 and len(sweet['how']):
33 sweet['created'] = datetime.utcnow().strftime(TIMESTAMP_FORMAT)
34 else:
35 return False
36 return sweet_list

templates/blank.html

1{% for obj in content %}1{% for obj in content %}
2<div>
2<div class="well">
3{% for key in content[obj].keys() %}3{% for key in content[obj].keys() %}
4<p>{{ key }}: {{ content[obj][key] }}</p>
4<p><b>{{ key }}</b>: {{ content[obj][key] }}</p>
5{% endfor %}5{% endfor %}
6</div>6</div>
7{% endfor %}7{% endfor %}

templates/web.html

4 <meta charset="utf-8">4 <meta charset="utf-8">
5 <meta http-equiv='imagetoolbar' content='no'/>5 <meta http-equiv='imagetoolbar' content='no'/>
6 <title> Web Annotation </title>6 <title> Web Annotation </title>
7 <link rel="stylesheet" type="text/css" href="static/bootstrap.css"></link>
8 <script type="text/javascript" src="static/jquery-1.9.1.min.js"></script>
9 <script type="text/javascript" src="static/bootstrap.js"></script>
7 <link rel="stylesheet" type="text/css" href="/static/bootstrap.css"></link>
8 <script type="text/javascript" src="/static/jquery-1.9.1.min.js"></script>
9 <script type="text/javascript" src="/static/bootstrap.js"></script>
10 <style type="text/css">10 <style type="text/css">
11 .container {11 .container {
12 margin-top: 30px;12 margin-top: 30px;