Commit 265ce2812a446606566c2886864e916fb460a5d7

JSON editor and history for demo

  Implemented a JSON editor, saving it and displaying the list of JSON
files. The saving doesn't work right now.
fetch.py
(41 / 0)
  
11from flask import Flask
22from flask import request
33from flask import render_template
4from flask import make_response
45import json
56import pymongo
7import os
8import glob
69
710app = Flask(__name__)
811
1515 return render_template('index.html',json=request.args['json'])
1616 else:
1717 return render_template('index.html')
18
19@app.route('/editor', methods=['GET'])
20def editor():
21 if request.args.has_key('json'):
22 filename = request.args['json']
23 else:
24 filename = 'test.json'
25 filename = os.path.join('static', filename)
26 try:
27 f = open(filename, 'r')
28 except:
29 f = open('static/test.json', 'r')
30 buf = f.read()
31 f.close()
32 return render_template('editor.html', json = buf)
33
34@app.route('/saveJSON', methods=['POST'])
35def saveJSON():
36 if request.form:
37 data = request.form
38 JSON = data['json']
39 filename = os.path.join('static', data['filename'])
40 f = open(filename, 'w')
41 f.write(JSON)
42 f.close()
43 return (data, 200)
44 else:
45 return (json.dumps(request.form), 200) # Bad Request
46
47@app.route('/history', methods=['GET'])
48def listJSON():
49 path = os.path.join('static', '*.json')
50 ls = glob.glob(path)
51 def sanitize(i):
52 return i.split('/')[-1]
53 ls = map(sanitize, ls)
54 return render_template('history.html', ls=ls)
55
1856
1957if __name__ == "__main__":
2058 app.run(debug=True, host='0.0.0.0')
static/jit.js
(36 / 27)
  
67646764 }
67656765 this.plot()
67666766 },
6767 reposition:function(){
6768 this.compute("end");
6769 var w=this.graph.getNode(this.root).pos.getc().scale(-1);
6770 e.Util.moebiusTransformation(this.graph,[w],["end"],"end","ignore");
6771 this.graph.eachNode(function(x){
6772 if(x.ignore){
6773 x.endPos.rho=x.pos.rho;
6774 x.endPos.theta=x.pos.theta
6775 }
6776 })
6767 reposition: function() {
6768 this.compute("end");
6769 var w=this.graph.getNode(this.root).pos.getc().scale(-1);
6770 e.Util.moebiusTransformation(this.graph,[w],["end"],"end","ignore");
6771 this.graph.eachNode(function(x) {
6772 if(x.ignore){
6773 x.endPos.rho=x.pos.rho;
6774 x.endPos.theta=x.pos.theta
6775 }
6776 });
67776777 },
6778 plot:function(){
6779 this.fx.plot()
6778 plot: function() {
6779 this.fx.plot();
67806780 },
6781 onClick:function(y,w){
6782// Ajay - Visual target selection
6783 if (this.graph.getNode(y)._angularWidth <= 0.5) {
6784 if (this.graph.getNode(y).data.band == "Character") {
6785 $("#character-value").html(this.graph.getNode(y).name);
6786 } else if (this.graph.getNode(y).data.band == "Jewellery") {
6787 $("#jewellery-value").html(this.graph.getNode(y).name);
6788 } else if (this.graph.getNode(y).data.band == "Material") {
6789 $("#material-value").html(this.graph.getNode(y).name);
6790 }
6791 }
6792// Ajay - end of visual target selection
6793 var x=this.graph.getNode(y).pos.getc(true);
6794 this.move(x,w)
6795 },
6781 tree_info_template: _.template($('#tree-info-template').html()),
6782 onClick: function(y, w) {
6783 // Ajay - Visual target selection
6784 /*if (this.graph.getNode(y)._angularWidth <= 0.5) {
6785 if (this.graph.getNode(y).data.band == "Character") {
6786 $("#character-value").html(this.graph.getNode(y).name);
6787 } else if (this.graph.getNode(y).data.band == "Jewellery") {
6788 $("#jewellery-value").html(this.graph.getNode(y).name);
6789 } else if (this.graph.getNode(y).data.band == "Material") {
6790 $("#material-value").html(this.graph.getNode(y).name);
6791 }
6792 }*/
6793 // Ajay - end of visual target selection
6794 var node = this.graph.getNode(y);
6795 var children = $jit.json.getSubtree(tree_json, node.id).children;
6796 if(_.isEmpty(children)) {
6797 $('#tree-info ul').append(this.tree_info_template({
6798 band: node.data.band,
6799 node: node.name
6800 }));
6801 }
6802 var x = node.pos.getc(true);
6803 this.move(x, w);
6804 },
67966805 move:function(A,y){
67976806 var x=r(A.x,A.y);
67986807 if(this.busy===false&&x.norm()<0.9){ // Ajay - make it clickable upto the depth of tree DIRECTLY. Increase in value = deeper the length.
  
1{
2 "id": "characteristics",
3 "name": "Characteristics",
4 "children": [
5 {
6 "id": "character",
7 "name": "Character",
8 "data": {
9 "band": "Characteristics",
10 "relation": "coordinators.html"
11 },
12 "children": [
13 {
14 "id": "shiva",
15 "name": "Shiva",
16 "data": {
17 "band": "Character",
18 "relation": "individual_ranganathan.html"
19 },
20 "children": []
21 },
22 {
23 "id": "parvathi",
24 "name": "Parvathi",
25 "data": {
26 "band": "Character",
27 "relation": "individual_sharat.html"
28 },
29 "children": []
30 },
31 {
32 "id": "ganesha",
33 "name": "Ganesha",
34 "data": {
35 "band": "Character",
36 "relation": "individual_sharat.html"
37 },
38 "children": []
39 },
40 {
41 "id": "bramha",
42 "name": "Bramha",
43 "data": {
44 "band": "Character",
45 "relation": "individual_sharat.html"
46 },
47 "children": []
48 },
49 {
50 "id": "vishnu",
51 "name": "Vishnu",
52 "data": {
53 "band": "Character",
54 "relation": "individual_sharat.html"
55 },
56 "children": []
57 },
58 {
59 "id": "krishna",
60 "name": "Krishna",
61 "data": {
62 "band": "Character",
63 "relation": "individual_muralimohan.html"
64 },
65 "children": []
66 },
67 {
68 "id": "radha",
69 "name": "Radha",
70 "data": {
71 "band": "Character",
72 "relation": "individual_muralimohan.html"
73 },
74 "children": []
75 }
76 ]
77 },
78 {
79 "id": "ornament",
80 "name": "Ornament",
81 "data": {
82 "band": "Characteristics",
83 "relation": "cultural.html"
84 },
85 "children": [
86 {
87 "id": "jewellery",
88 "name": "Jewellery",
89 "data": {
90 "band": "Ornament"
91 },
92 "children": [
93 {
94 "id": "ear-ring",
95 "name": "Ear-ring",
96 "data": {
97 "band": "Jewellery"
98 },
99 "children": []
100 },
101 {
102 "id": "ring",
103 "name": "Ring",
104 "data": {
105 "band": "Jewellery"
106 },
107 "children": []
108 },
109 {
110 "id": "nose-ring",
111 "name": "Nose-ring",
112 "data": {
113 "band": "Jewellery",
114 "relation": "project_murals.html"
115 },
116 "children": []
117 },
118 {
119 "id": "pendent",
120 "name": "Pendent",
121 "data": {
122 "band": "Jewellery",
123 "relation": "project_murals.html"
124 },
125 "children": []
126 },
127 {
128 "id": "ankelet",
129 "name": "Ankelet",
130 "data": {
131 "band": "Jewellery",
132 "relation": "project_murals.html"
133 },
134 "children": []
135 },
136 {
137 "id": "bracelet",
138 "name": "Bracelet",
139 "data": {
140 "band": "Jewellery",
141 "relation": "project_murals.html"
142 },
143 "children": []
144 },
145 {
146 "id": "bangles",
147 "name": "Bangles",
148 "data": {
149 "band": "Jewellery",
150 "relation": "project_murals.html"
151 },
152 "children": []
153 }
154 ]
155 },
156 {
157 "id": "material",
158 "name": "Material",
159 "data": {
160 "band": "Ornament",
161 "relation": "project_knowledge.html"
162 },
163 "children": [
164 {
165 "id": "gold",
166 "name": "Gold",
167 "data": {
168 "band": "Material",
169 "relation": "project_murals.html"
170 },
171 "children": []
172 },
173 {
174 "id": "silver",
175 "name": "Silver",
176 "data": {
177 "band": "Material",
178 "relation": "project_murals.html"
179 },
180 "children": []
181 },
182 {
183 "id": "bronze",
184 "name": "Bronze",
185 "data": {
186 "band": "Material",
187 "relation": "project_murals.html"
188 },
189 "children": []
190 },
191 {
192 "id": "ruby",
193 "name": "Ruby",
194 "data": {
195 "band": "Material",
196 "relation": "project_murals.html"
197 },
198 "children": []
199 },
200 {
201 "id": "copper",
202 "name": "Copper",
203 "data": {
204 "band": "Material",
205 "relation": "project_murals.html"
206 },
207 "children": []
208 },
209 {
210 "id": "diamond",
211 "name": "Diamond",
212 "data": {
213 "band": "Material",
214 "relation": "project_murals.html"
215 },
216 "children": []
217 },
218 {
219 "id": "topaz",
220 "name": "Topaz",
221 "data": {
222 "band": "Material",
223 "relation": "project_murals.html"
224 },
225 "children": []
226 }
227 ]
228 }
229 ]
230 }
231 ],
232 "data": {
233 "relation": "index.html"
234 }
235}
  
6464 "children":[]
6565 }
6666 ]}
67 ]}
67 ],
68 "data": {
69 "relation": "index.html"
70 }
71}
static/tree.js
(13 / 221)
  
1var labelType, useGradients, nativeTextSupport, animate, ht;
1var labelType, useGradients, nativeTextSupport, animate, ht, tree_json;
22
33(function() {
44 var ua = navigator.userAgent,
1313 nativeTextSupport = labelType == 'Native';
1414 useGradients = nativeCanvasSupport;
1515 animate = !(iStuff || !nativeCanvasSupport);
16})();
1716
18function inits(){
19 //init data
20 var json = {
21 "id": "characteristics",
22 "name": "Characteristics",
23 "children": [
24 // Location
25 {
26 "id": "character",
27 "name": "Character",
28 "data": {
29 "band": "Characteristics",
30 "relation": "coordinators.html"
31 },
32 "children": [{
33 "id": "shiva",
34 "name": "Shiva",
35 "data": {
36 "band": "Character",
37 "relation": "individual_ranganathan.html"
38 },
39 "children": []
17 //load JSON data.
18 // FIXME: the url is hardcoded, maybe you have to change it
19 // if the file is a variable one
20 $.getJSON('static/old.json', function(json) {
21 console.log('json', json);
22 tree_json = json;
23 inits();
24 });
4025
41 }, {
42 "id": "parvathi",
43 "name": "Parvathi",
44 "data": {
45 "band": "Character",
46 "relation": "individual_sharat.html"
47 },
48 "children": []
49 }, {
50 "id": "ganesha",
51 "name": "Ganesha",
52 "data": {
53 "band": "Character",
54 "relation": "individual_sharat.html"
55 },
56 "children": []
57 }, {
58 "id": "bramha",
59 "name": "Bramha",
60 "data": {
61 "band": "Character",
62 "relation": "individual_sharat.html"
63 },
64 "children": []
65 }, {
66 "id": "vishnu",
67 "name": "Vishnu",
68 "data": {
69 "band": "Character",
70 "relation": "individual_sharat.html"
71 },
72 "children": []
73 }, {
74 "id": "krishna",
75 "name": "Krishna",
76 "data": {
77 "band": "Character",
78 "relation": "individual_muralimohan.html"
79 },
80 "children": []
81 }, {
82 "id": "radha",
83 "name": "Radha",
84 "data": {
85 "band": "Character",
86 "relation": "individual_muralimohan.html"
87 },
88 "children": []
89 }]
90 },
91 // Languages
92 {
93 "id": "ornament",
94 "name": "Ornament",
95 "data": {
96 "band": "Characteristics",
97 "relation": "cultural.html"
98 },
99 "children": [{
100 "id": "jewellery",
101 "name": "Jewellery",
102 "data": {
103 "band": "Ornament"
104 // "relation": "project_murals.html"
105 },
106 "children": [{
107 "id": "ear-ring",
108 "name": "Ear-ring",
109 "data": {
110 "band": "Jewellery"
111 // "relation": "project_murals.html"
112 },
113 "children": []
114 },{
115 "id": "ring",
116 "name": "Ring",
117 "data": {
118 "band": "Jewellery"
119 // "relation": "project_murals.html"
120 },
121 "children": []
122 },{
123 "id": "nose-ring",
124 "name": "Nose-ring",
125 "data": {
126 "band": "Jewellery",
127 "relation": "project_murals.html"
128 },
129 "children": []
130 },{
131 "id": "pendent",
132 "name": "Pendent",
133 "data": {
134 "band": "Jewellery",
135 "relation": "project_murals.html"
136 },
137 "children": []
138 },{
139 "id": "ankelet",
140 "name": "Ankelet",
141 "data": {
142 "band": "Jewellery",
143 "relation": "project_murals.html"
144 },
145 "children": []
146 },{
147 "id": "bracelet",
148 "name": "Bracelet",
149 "data": {
150 "band": "Jewellery",
151 "relation": "project_murals.html"
152 },
153 "children": []
154 },{
155 "id": "bangles",
156 "name": "Bangles",
157 "data": {
158 "band": "Jewellery",
159 "relation": "project_murals.html"
160 },
161 "children": []
162 }]
163 }, {
164 "id": "material",
165 "name": "Material",
166 "data": {
167 "band": "Ornament",
168 "relation": "project_knowledge.html"
169 },
170 "children": [{
171 "id": "gold",
172 "name": "Gold",
173 "data": {
174 "band": "Material",
175 "relation": "project_murals.html"
176 },
177 "children": []
178 },{
179 "id": "silver",
180 "name": "Silver",
181 "data": {
182 "band": "Material",
183 "relation": "project_murals.html"
184 },
185 "children": []
186 },{
187 "id": "bronze",
188 "name": "Bronze",
189 "data": {
190 "band": "Material",
191 "relation": "project_murals.html"
192 },
193 "children": []
194 },{
195 "id": "ruby",
196 "name": "Ruby",
197 "data": {
198 "band": "Material",
199 "relation": "project_murals.html"
200 },
201 "children": []
202 },{
203 "id": "copper",
204 "name": "Copper",
205 "data": {
206 "band": "Material",
207 "relation": "project_murals.html"
208 },
209 "children": []
210 },{
211 "id": "diamond",
212 "name": "Diamond",
213 "data": {
214 "band": "Material",
215 "relation": "project_murals.html"
216 },
217 "children": []
218 },{
219 "id": "topaz",
220 "name": "Topaz",
221 "data": {
222 "band": "Material",
223 "relation": "project_murals.html"
224 },
225 "children": []
226 }]
227 }]
228 }],
229 "data": {
230 "relation": "index.html"
231 }
232 };
233 //end
26})();
27
28function inits() {
23429 var infovis = document.getElementById('infovis');
23530 var w = infovis.offsetWidth + 500; var h = infovis.offsetHeight + 385;
23631
100100 style.left = (left - w / 2) + 'px';
101101 },
102102 });
103 //load JSON data.
104 ht.loadJSON(json);
103 ht.loadJSON(tree_json);
105104 //compute positions and plot.
106105 ht.refresh();
107106 //end
108107 ht.controller.onComplete();
109108}
110
111document.addEventListener("DOMContentLoaded", inits, false);
  
1<!DOCTYPE html>
2<html>
3<head>
4 <title>Lepakshi Mural - JSON editor</title>
5 <link rel="stylesheet" type="text/css" href="static/bootstrap.css"></link>
6 <meta charset="utf-8" />
7 <style>
8 textarea {
9 width: 500px;
10 }
11 </style>
12</head>
13<body>
14 <p></p><br>
15 <div class="container">
16 <h3> JSON Editor </h3>
17 <div id="json-saved" class="alert alert-success" style="display: none; width: 300px; margin: auto;">
18 <button type="button" class="close" data-dismiss="alert">&times;</button>
19 <b>Success!</b> JSON saved. See <a href="/history">here</a>
20 </div>
21 <div id="json-error" class="alert alert-error" style="display: none; width: 300px; margin: auto;">
22 <button type="button" class="close" data-dismiss="alert">&times;</button>
23 <b>Invalid JSON!</b> Verify at <a href="http://jsonlint.com">jsonlint.com</a>
24 </div>
25 <textarea id="json" rows="30">
26 {{ json }}
27 </textarea>
28 Enter JSON filename
29 <input type="text" id="filename" placeholder="newname.json">
30 <button class="btn" onclick="save();"> Save </button>
31 </div>
32 <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
33 <script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
34 <script type="text/javascript" src="static/bootstrap.js"></script>
35 <script>
36 function save() {
37 var json = $('#json').val();
38 var filename = $('#filename').val();
39 if(!filename.match(/.json$/)) {
40 filename += '.json';
41 }
42 try {
43 json = JSON.parse(json);
44 console.log(json);
45 console.log(filename);
46 $.post('/saveJSON', {"json": json, "filename": filename}, function(data) {
47 console.log(data);
48 $('#json-saved').show();
49 }, 'json');
50 } catch(e) {
51 $('#json-error').show();
52 }
53 }
54 </script>
55</body>
56</html>
  
1<!DOCTYPE html>
2<html>
3<head>
4 <title>Lepakshi Mural - JSON history</title>
5 <link rel="stylesheet" type="text/css" href="static/bootstrap.css"></link>
6 <meta charset="utf-8" />
7</head>
8<body>
9 <div class="container">
10 <h3> JSON history </h3>
11 <ul>
12 {% for file in ls %}
13 <li><a href="/editor?{{ file }}">{{ file }}</a></li>
14 {% endfor %}
15 </ul>
16 </div>
17</body>
18</html>
  
1010 <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
1111 <script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
1212 <script type="text/javascript" src="http://backbonejs.org/backbone-min.js"></script>
13 <script type="text/javascript" src="static/jit.js"></script>
1413 <script type="text/javascript" src="static/tree.js"></script>
1514 <style type='text/css'>
1615 /*#annotation-tree {
2323 z-index:99999;
2424 }*/
2525 </style>
26 <title>Flask Lepakshi Mural</title>
26 <title>Lepakshi Mural</title>
2727 <meta http-equiv='imagetoolbar' content='no'/>
2828 <link rel="stylesheet" type="text/css" href="static/bootstrap.css"></link>
2929 <!--link rel="stylesheet" type="text/css" href="./tree.css"></link-->
8383 <button type="button" class="close" data-dismiss="alert">&times;</button>
8484 <b>Success!</b> Post successfully posted.
8585 </div>
86 <div id="tree-json-loaded" class="alert alert-success" style="display: none; width: 300px; margin: auto;">
87 <button type="button" class="close" data-dismiss="alert">&times;</button>
88 <b>Success!</b> New JSON loaded.
89 </div>
8690
8791 <div class="btn-group">
8892 <button onclick="handler.trigger();" class="btn btn-small">Mural</button>
9696
9797 <p></p>
9898
99 <input type="text" id="tree-json-file" value="old.json">
100 <button class="btn" id="load-tree-json" onclick="loadTreeJSON();">Load JSON</button>
101 <button class="btn" id="edit-tree-json" onclick="editTreeJSON();">Edit JSON</button>
102 <p></p>
99103 <div id="map"></div>
100104
101105 <div id="subheader">Generated by <a href="http://www.maptiler.org/">MapTiler</a><a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>, Copyright &copy; 2008 <a href="http://www.klokan.cz/">Klokan Petr Pridal</a>, <a href="http://www.gdal.org/">GDAL</a> &amp; <a href="http://www.osgeo.org/">OSGeo</a> <a href="http://code.google.com/soc/">GSoC</a>
107107 </div>
108108
109109 <div class="edit-json">
110 <button id="edit-json-btn" class="btn" onclick="editJSON();">Edit JSON manually</button>
111 <textarea rows="3" id="edit-json" style="display: none;"></textarea>
110 <button id="edit-json-btn" class="btn" onclick="editJSON();">Edit JSON to tweet</button>
111 <textarea rows="20" cols="50" id="edit-json" style="display: none;"></textarea>
112112 <button class="btn" id="save-json" style="display: none;" onclick="saveJSON();">Save</button>
113113 </div>
114114
125125 </div>
126126 </div>
127127 <div class="modal-body">
128 <div id="infovis">
129 <div class="well text-info">
130 <ul>
131 <li><b>Character:</b> <span id="character-value"></span></li>
132 <li>
133 <b>Ornament:</b>
134 <ul>
135 <li><b>Material:</b> <span id="material-value"></span></li>
136 <li><b>Jewellery:</b> <span id="jewellery-value"></span></li>
137 </ul>
138 </li>
139 </ul>
140 </div>
128 <div id="infovis"> </div>
129 <div id="tree-info" class="well text-info">
130 <ul></ul>
141131 </div>
142132 </div>
143133 <div class="modal-footer">
136136 </div>
137137 </div>
138138
139 <script type="text/template" id="tree-info-template">
140 <li><b><%= band %></b>: <span id="<%= node %>-value"><%= node %></span></li>
141 </script>
142
139143 <script type="text/javascript">
140144 function annotationTree() {
141145 $('#annotation-tree').modal();
165165 }
166166 function treeClose() {
167167 $('#annotation-tree').modal('hide');
168 attribs["character"] = $("#character-value").text();
169 attribs["material"] = $("#material-value").text();
168 $('#tree-info ul li').each(function(idx, elem) {
169 var key = $(elem).find('b').text().toLowerCase();
170 var val = $(elem).find('span').text().toLowerCase();
171 attribs[key] = val;
172 });
170173 myJSON.push(attribs);
171174 $("#publish").attr("disabled", false);
172175 }
176 function loadTreeJSON() {
177 var file = $('#tree-json-file').val();
178 $.getJSON('static/'+file, function(json) {
179 ht.loadJSON(json);
180 ht.refresh();
181 ht.controller.onComplete();
182 $('#tree-json-loaded').show();
183 });
184 }
185 function editTreeJSON() {
186 var json = $('#tree-json-loaded').val();
187 window.open('/editor?json='+json);
188 }
173189 </script>
174
175 {% if json %}
176 <script type="text/javascript">
177
178 $.get({{ json|string|safe }} , function(data){
179 console.log(data);
180 ht.loadJSON(data);
181 //compute positions and plot.
182 ht.refresh();
183 //end
184 ht.controller.onComplete();
185
186}, 'json');
187 </script>
188 {% endif %}
189
190 <script type="text/javascript" src="static/jit.js"></script>
190191</body>
191192</html>