Commit 2431ed7933f1ccc58cca2210b879873dcd59e924
Initial implementation of external API source (Open Cuultur Data)
- An intial version to search in the Open Cuultur Data APIs and annotate
images from search results. Right now fetching, and displaying of search
results is implemented along with first attempt at annotating search result
images.
| | | | 7 | | 7 | |
---|
8 | requires = [ | 8 | requires = [ |
---|
9 | 'Flask', | 9 | 'Flask', |
---|
10 | 'requests' | | 'requests' |
---|
| | 10 | 'requests', | | | 11 | 'lxml' |
---|
11 | ] | 12 | ] |
---|
12 | | 13 | |
---|
13 | setup(name='Swtr', | 14 | setup(name='Swtr', |
---|
| | | | 3 | import flask | 3 | import flask |
---|
4 | from flask import session | 4 | from flask import session |
---|
5 | import lxml.html | 5 | import lxml.html |
---|
6 | import config | | import config |
---|
7 | import requests | 6 | import requests |
---|
8 | import json | 7 | import json |
---|
9 | import StringIO | 8 | import StringIO |
---|
10 | import imghdr | 9 | import imghdr |
---|
11 | from datetime import datetime, timedelta | 10 | from datetime import datetime, timedelta |
---|
12 | | 11 | |
---|
| | 12 | import config |
---|
13 | | 13 | |
---|
| | 14 | |
---|
14 | app = flask.Flask(__name__) | 15 | app = flask.Flask(__name__) |
---|
15 | app.config['SECRET_KEY'] = config.secret_key | 16 | app.config['SECRET_KEY'] = config.secret_key |
---|
16 | | 17 | |
---|
… | | … | |
---|
81 | url=flask.request.args.get('where')) | 81 | url=flask.request.args.get('where')) |
---|
82 | | 82 | |
---|
83 | | 83 | |
---|
| | 84 | # endpoint to search the Open Cuultur Data APIs |
---|
| | 85 | # takes in `query`, `size`, and `from` parameters in query string |
---|
| | 86 | # returns a JSON response |
---|
| | 87 | @app.route('/search/ocd', methods=['GET']) |
---|
| | 88 | def search_ocd(): |
---|
| | 89 | query = flask.request.args.get('query') |
---|
| | 90 | #collection = flask.request.args.get('collection') |
---|
| | 91 | size = flask.request.args.get('size') or 10 |
---|
| | 92 | offset = flask.request.args.get('from') or 0 |
---|
| | 93 | |
---|
| | 94 | # if query parameter is not passed, return bad request. |
---|
| | 95 | if not query: |
---|
| | 96 | flask.abort(400) |
---|
| | 97 | |
---|
| | 98 | payload = { |
---|
| | 99 | 'query': query, |
---|
| | 100 | 'facets': { |
---|
| | 101 | 'collection': {}, |
---|
| | 102 | 'date': {'interval': 'day'} |
---|
| | 103 | }, |
---|
| | 104 | 'filters': { |
---|
| | 105 | 'media_content_type': {'terms': ['image/jpeg', 'image/png']} |
---|
| | 106 | }, |
---|
| | 107 | 'size': size, |
---|
| | 108 | 'from': offset |
---|
| | 109 | } |
---|
| | 110 | resp = requests.post('http://api.opencultuurdata.nl/v0/search', |
---|
| | 111 | data=json.dumps(payload)) |
---|
| | 112 | |
---|
| | 113 | response = flask.make_response() |
---|
| | 114 | response.data = json.dumps(resp.json()) |
---|
| | 115 | response.headers['Content-type'] = 'application/json' |
---|
| | 116 | return response |
---|
| | 117 | |
---|
| | 118 | |
---|
| | 119 | # resolve OCD Media URLs: http://docs.opencultuurdata.nl/user/api.html#resolver |
---|
| | 120 | @app.route('/resolve-ocd-media/<media_hash>', methods=['GET']) |
---|
| | 121 | def resolve_ocd_media_urls(media_hash): |
---|
| | 122 | |
---|
| | 123 | resp = requests.get('http://api.opencultuurdata.nl/v0/resolve/' + |
---|
| | 124 | media_hash) |
---|
| | 125 | |
---|
| | 126 | response = flask.make_response() |
---|
| | 127 | response.data = resp.url |
---|
| | 128 | return response |
---|
| | 129 | |
---|
| | 130 | |
---|
84 | @app.route('/annotate', methods=['GET']) | 131 | @app.route('/annotate', methods=['GET']) |
---|
85 | def annotate(): | 132 | def annotate(): |
---|
86 | print flask.request.args['where'] | | print flask.request.args['where'] |
---|
87 | # img = urllib2.urlopen(flask.request.args['where']).read() | 133 | # img = urllib2.urlopen(flask.request.args['where']).read() |
---|
88 | request = requests.get(flask.request.args['where']) | 134 | request = requests.get(flask.request.args['where']) |
---|
89 | content = request.text | 135 | content = request.text |
---|
… | | … | |
---|
188 | "js/lib/backbone-1.0.0.min.js")) | 188 | "js/lib/backbone-1.0.0.min.js")) |
---|
189 | backboneJS.set("type", "text/javascript") | 189 | backboneJS.set("type", "text/javascript") |
---|
190 | | 190 | |
---|
| | 191 | # annotorious plugin |
---|
| | 192 | annotoriousCSS = root.makeelement('link') |
---|
| | 193 | root.body.append(annotoriousCSS) |
---|
| | 194 | annotoriousCSS.set("href", flask.url_for('static', |
---|
| | 195 | filename='css/annotorious.css')) |
---|
| | 196 | annotoriousCSS.set('rel', 'stylesheet') |
---|
| | 197 | |
---|
| | 198 | annotoriousJS = root.makeelement('script') |
---|
| | 199 | root.body.append(annotoriousJS) |
---|
| | 200 | annotoriousJS.set('src', flask.url_for('static', |
---|
| | 201 | filename='js/annotorious.okfn.0.3.js')) |
---|
| | 202 | |
---|
191 | if 'auth_tok' in session: | 203 | if 'auth_tok' in session: |
---|
192 | auth_tok = session['auth_tok'] | 204 | auth_tok = session['auth_tok'] |
---|
193 | else: | 205 | else: |
---|
… | | … | |
---|
261 | refresh_token=auth_tok['refresh_token'], | 261 | refresh_token=auth_tok['refresh_token'], |
---|
262 | config=config, | 262 | config=config, |
---|
263 | url=flask.request.args.get('where')) | 263 | url=flask.request.args.get('where')) |
---|
264 | | | |
---|
265 | | | |
---|
266 | @app.route("/search") | | @app.route("/search") |
---|
267 | def search(): | | def search(): |
---|
268 | if 'size' not in flask.request.args: | | if 'size' not in flask.request.args: |
---|
269 | size = 10 | | size = 10 |
---|
270 | else: | | else: |
---|
271 | size = flask.request.args['size'] | | size = flask.request.args['size'] |
---|
272 | if 'from' not in flask.request.args: | | if 'from' not in flask.request.args: |
---|
273 | fr = 0 | | fr = 0 |
---|
274 | else: | | else: |
---|
275 | fr = flask.request.args['from'] | | fr = flask.request.args['from'] |
---|
276 | | | |
---|
277 | results = requests.post("http://api.opencultuurdata.nl/v0/search", | | results = requests.post("http://api.opencultuurdata.nl/v0/search", |
---|
278 | data=json.dumps({ | | data=json.dumps({ |
---|
279 | "query": flask.request.args['term'], | | "query": flask.request.args['term'], |
---|
280 | "facets": {"collection": {}, | | "facets": {"collection": {}, |
---|
281 | "date": {"interval": "day"}}, | | "date": {"interval": "day"}}, |
---|
282 | "filters": {"media_content_type": | | "filters": {"media_content_type": |
---|
283 | {"terms": ["image/jpeg", | | {"terms": ["image/jpeg", |
---|
284 | "image/png"]}}, | | "image/png"]}}, |
---|
285 | "size": size, | | "size": size, |
---|
286 | "from": fr})) | | "from": fr})) |
---|
287 | return flask.jsonify(results.json()) | | return flask.jsonify(results.json()) |
---|
288 | | 264 | |
---|
289 | | 265 | |
---|
290 | # if the app is run directly from command-line | 266 | # if the app is run directly from command-line |
---|
| | | | 10 | min-height: 35px; | 10 | min-height: 35px; |
---|
11 | } | 11 | } |
---|
12 | | 12 | |
---|
13 | | | |
---|
14 | #swt-maker { | 13 | #swt-maker { |
---|
15 | } | 14 | } |
---|
| | 15 | |
---|
| | 16 | #control-panel { |
---|
| | 17 | margin-top: 10px; |
---|
| | 18 | margin-left: 0; |
---|
| | 19 | } |
---|
| | 20 | |
---|
16 | #signinview { | 21 | #signinview { |
---|
17 | margin 0 20px; | 22 | margin 0 20px; |
---|
18 | padding: 10px; | 23 | padding: 10px; |
---|
19 | text-align: center; | 24 | text-align: center; |
---|
20 | } | 25 | } |
---|
21 | #img-annotation-wrapper { | | #img-annotation-wrapper { |
---|
| | 26 | | | | 27 | #img-annotation-wrapper, #ocd-results { |
---|
22 | margin: 30px auto 0 auto; | 28 | margin: 30px auto 0 auto; |
---|
23 | } | 29 | } |
---|
| | 30 | |
---|
24 | #annotatable-img { | 31 | #annotatable-img { |
---|
25 | margin: 0 auto; | 32 | margin: 0 auto; |
---|
26 | max-width: 1125px; | 33 | max-width: 1125px; |
---|
27 | } | 34 | } |
---|
| | 35 | |
---|
28 | #sweet-list-wrapper { | 36 | #sweet-list-wrapper { |
---|
29 | width: 500px; | 37 | width: 500px; |
---|
30 | min-height: 300px; | 38 | min-height: 300px; |
---|
… | | … | |
---|
46 | padding: 30px; | 46 | padding: 30px; |
---|
47 | display: none; | 47 | display: none; |
---|
48 | } | 48 | } |
---|
| | 49 | |
---|
49 | #sweet-list { | 50 | #sweet-list { |
---|
50 | margin-bottom: 10px; | 51 | margin-bottom: 10px; |
---|
51 | } | 52 | } |
---|
52 | .btn-grp { | | .btn-grp { |
---|
53 | position: relative; | | position: relative; |
---|
54 | bottom: -10%; | | bottom: -10%; |
---|
55 | right: -10%; | | right: -10%; |
---|
| | 53 | | | | 54 | .ocd-item { |
---|
| | 55 | padding-bottom: 4px; |
---|
| | 56 | border: 1px solid #ddd; |
---|
| | 57 | border-radius: 4px; |
---|
| | 58 | margin-bottom: 20px; |
---|
| | 59 | text-align: center; |
---|
56 | } | 60 | } |
---|
| | 61 | |
---|
| | 62 | .thumb-image { |
---|
| | 63 | background-position: center center; |
---|
| | 64 | background-repeat: no-repeat; |
---|
| | 65 | background-size: cover; |
---|
| | 66 | display: block; |
---|
| | 67 | height: 400px; |
---|
| | 68 | margin: 0 auto; |
---|
| | 69 | } |
---|
| | 70 | |
---|
57 | #sweet { | 71 | #sweet { |
---|
58 | display: none; | 72 | display: none; |
---|
59 | } | 73 | } |
---|
| | 74 | |
---|
60 | #helpview { | 75 | #helpview { |
---|
61 | font-weight: bold; | 76 | font-weight: bold; |
---|
62 | font-size: 1.3em; | 77 | font-size: 1.3em; |
---|
| | | | 130 | this.annotator = new Annotator(document.body); | 130 | this.annotator = new Annotator(document.body); |
---|
131 | swtr.anno = this.annotator; | 131 | swtr.anno = this.annotator; |
---|
132 | this.annotator.addPlugin("Tags"); | 132 | this.annotator.addPlugin("Tags"); |
---|
| | 133 | this.annotator.addPlugin("AnnotoriousImagePlugin"); |
---|
133 | this.listenTo(this.collection, "add", this.loadAnno); | 134 | this.listenTo(this.collection, "add", this.loadAnno); |
---|
134 | this.annotator.subscribe("annotationCreated", this.storeAnno); | 135 | this.annotator.subscribe("annotationCreated", this.storeAnno); |
---|
135 | }, | 136 | }, |
---|
| | | | 233 | cleanUp: function() { | 233 | cleanUp: function() { |
---|
234 | //console.log('cleaning up'); | 234 | //console.log('cleaning up'); |
---|
235 | $(this.el).hide(); | 235 | $(this.el).hide(); |
---|
| | 236 | if(swtr.appView.source === 'ocd') { |
---|
| | 237 | $('#img-annotation-wrapper').hide(); |
---|
| | 238 | $('#ocd-results').show(); |
---|
| | 239 | } |
---|
236 | } | 240 | } |
---|
237 | }); | 241 | }); |
---|
238 | | 242 | |
---|
239 | var AppView = Backbone.View.extend({ | 243 | var AppView = Backbone.View.extend({ |
---|
240 | el: $('#swt-maker'), | 244 | el: $('#swt-maker'), |
---|
241 | events: { | 245 | events: { |
---|
242 | 'click #img-url-load': 'setImage', | | 'click #img-url-load': 'setImage', |
---|
243 | 'click #img-url-submit': 'setImage', | | 'click #img-url-submit': 'setImage', |
---|
| | 246 | 'click #user-input-submit': 'submitUserInput', | 244 | 'click #sweet': 'sweet', | 247 | 'click #sweet': 'sweet', |
---|
245 | 'click #sign-in': 'signIn', | 248 | 'click #sign-in': 'signIn', |
---|
246 | 'click #setbox': 'showHide', | 249 | 'click #setbox': 'showHide', |
---|
247 | 'change #custom-dropdown ': 'getFormValue' | | 'change #custom-dropdown ': 'getFormValue' |
---|
| | 250 | 'change #custom-dropdown ': 'getFormValue', | | | 251 | 'click #ocd-source': 'sourceChanged' |
---|
248 | //'mouseup .annotorious-editor-button-save': 'addnew_anno' | 252 | //'mouseup .annotorious-editor-button-save': 'addnew_anno' |
---|
249 | }, | 253 | }, |
---|
250 | initialize: function() { | 254 | initialize: function() { |
---|
251 | // initialize components | 255 | // initialize components |
---|
| | 256 | this.source = 'none'; |
---|
252 | this.helpview = new HelpView(); | 257 | this.helpview = new HelpView(); |
---|
253 | this.sweetsview = new SweetsView({collection: swtr.sweets}); | 258 | this.sweetsview = new SweetsView({collection: swtr.sweets}); |
---|
254 | | 259 | |
---|
… | | … | |
---|
282 | this.imgURL = this.$img.attr('src'); | 282 | this.imgURL = this.$img.attr('src'); |
---|
283 | if(this.imgURL) { | 283 | if(this.imgURL) { |
---|
284 | this.initImageAnno(); | 284 | this.initImageAnno(); |
---|
285 | $('#img-url-input').val(this.imgURL); | | $('#img-url-input').val(this.imgURL); |
---|
| | 285 | $('#user-input').val(this.imgURL); | 286 | } | 286 | } |
---|
287 | else { | 287 | else { |
---|
288 | this.helpview.step(1); | 288 | this.helpview.step(1); |
---|
… | | … | |
---|
297 | scopes: 'email,sweet' | 297 | scopes: 'email,sweet' |
---|
298 | }); | 298 | }); |
---|
299 | }, | 299 | }, |
---|
300 | setImage: function(event) { | | setImage: function(event) { |
---|
| | 300 | submitUserInput: function(event) { | 301 | event.preventDefault(); | 301 | event.preventDefault(); |
---|
302 | var url = $('#img-url-input').val(); | | var url = $('#img-url-input').val(); |
---|
| | 302 | var input = $('#user-input').val(); | | | 303 | if(this.source === 'ocd') { |
---|
| | 304 | this.loadOCDSearch(input); |
---|
| | 305 | } |
---|
| | 306 | else if (this.source === 'none') { |
---|
| | 307 | this.loadURL(input); |
---|
| | 308 | } |
---|
| | 309 | }, |
---|
| | 310 | loadURL: function(url) { |
---|
| | 311 | $('#ocd-results').hide(); |
---|
| | 312 | $('#img-annotation-wrapper').show(); |
---|
| | 313 | if(!url) { |
---|
| | 314 | return false; |
---|
| | 315 | } |
---|
| | 316 | // if image url then load the image annotation |
---|
303 | if(url.match(/.jpg|.jpeg|.png|.gif|.bmp|.svg/)) { | 317 | if(url.match(/.jpg|.jpeg|.png|.gif|.bmp|.svg/)) { |
---|
304 | | 318 | |
---|
305 | this.imgURL = $('#img-url-input').val(); | | this.imgURL = $('#img-url-input').val(); |
---|
306 | if(!this.imgURL) { | | if(!this.imgURL) { |
---|
307 | return false; | | return false; |
---|
308 | } | | } |
---|
| | 319 | this.imgURL = url; | | | 320 | |
---|
309 | if(this.$img.attr('src') === this.imgURL) { | 321 | if(this.$img.attr('src') === this.imgURL) { |
---|
310 | return; | 322 | return; |
---|
311 | } | 323 | } |
---|
… | | … | |
---|
328 | this.$img.attr('src', this.imgURL); | 328 | this.$img.attr('src', this.imgURL); |
---|
329 | return false; | 329 | return false; |
---|
330 | } | 330 | } |
---|
| | 331 | // else load text annotation |
---|
331 | else { | 332 | else { |
---|
332 | if(!url) { | | if(!url) { |
---|
333 | return false; | | return false; |
---|
334 | } | | } |
---|
335 | window.location.href = '/annotate?where=' + url; | 333 | window.location.href = '/annotate?where=' + url; |
---|
336 | } | 334 | } |
---|
337 | }, | 335 | }, |
---|
… | | … | |
---|
552 | userLoggedOut: function() { | 552 | userLoggedOut: function() { |
---|
553 | swtr.who = 'Guest'; | 553 | swtr.who = 'Guest'; |
---|
554 | $('#signinview').html('Logged out'); | 554 | $('#signinview').html('Logged out'); |
---|
| | 555 | }, |
---|
| | 556 | changeURLInputPlaceholder: function(source) { |
---|
| | 557 | switch (source) { |
---|
| | 558 | case 'ocd' : $('#user-input').attr('placeholder', 'Enter search query'); |
---|
| | 559 | break; |
---|
| | 560 | case 'none' : $('#user-input').attr('placeholder', 'Enter URL of image or web page'); |
---|
| | 561 | break; |
---|
| | 562 | } |
---|
| | 563 | }, |
---|
| | 564 | // function to change the source in the application and update the UI |
---|
| | 565 | changeSource: function(source) { |
---|
| | 566 | switch (source) { |
---|
| | 567 | case 'ocd' : this.source = 'ocd'; |
---|
| | 568 | this.helpview.step(11); |
---|
| | 569 | this.changeURLInputPlaceholder('ocd'); |
---|
| | 570 | break; |
---|
| | 571 | case 'none' : this.source = 'none'; |
---|
| | 572 | this.helpview.step(1); |
---|
| | 573 | this.changeURLInputPlaceholder('none'); |
---|
| | 574 | break; |
---|
| | 575 | } |
---|
| | 576 | }, |
---|
| | 577 | // event handler to capture control panel UI change of source |
---|
| | 578 | sourceChanged: function(event) { |
---|
| | 579 | if($('#ocd-source').is(':checked')) { |
---|
| | 580 | this.changeSource('ocd'); |
---|
| | 581 | } |
---|
| | 582 | else { |
---|
| | 583 | this.changeSource('none'); |
---|
| | 584 | } |
---|
| | 585 | }, |
---|
| | 586 | loadOCDSearch: function(input) { |
---|
| | 587 | var self = this; |
---|
| | 588 | $('#img-annotation-wrapper').hide(); |
---|
| | 589 | $('#ocd-results').show(); |
---|
| | 590 | $('#ocd-results').append('Loading..'); |
---|
| | 591 | $.ajax({ |
---|
| | 592 | type: 'GET', |
---|
| | 593 | url: '/search/ocd', |
---|
| | 594 | data: {query: input}, |
---|
| | 595 | success: function(data) { |
---|
| | 596 | self.ocdView = new OCDView({model: data.hits.hits}); |
---|
| | 597 | } |
---|
| | 598 | }); |
---|
555 | } | 599 | } |
---|
556 | }); | 600 | }); |
---|
557 | | 601 | |
---|
| | 602 | var OCDView = Backbone.View.extend({ |
---|
| | 603 | el: $('#ocd-results'), |
---|
| | 604 | events: { |
---|
| | 605 | 'click .ocd-item a': 'onClickImg' |
---|
| | 606 | }, |
---|
| | 607 | initialize: function() { |
---|
| | 608 | this.item_template = _.template($('#ocd-item-template').html()); |
---|
| | 609 | this.render(); |
---|
| | 610 | }, |
---|
| | 611 | render: function() { |
---|
| | 612 | var $row_el; |
---|
| | 613 | this.$el.html(''); |
---|
| | 614 | _.each(this.model, function(item, idx) { |
---|
| | 615 | if(idx % 3 === 0) { |
---|
| | 616 | $row_el = $('<div class="row"></div>'); |
---|
| | 617 | this.$el.append($row_el); |
---|
| | 618 | } |
---|
| | 619 | $row_el.append(this.item_template({ |
---|
| | 620 | title: item._source.title, |
---|
| | 621 | media_url: item._source.media_urls[0].url, |
---|
| | 622 | authors: item._source.authors |
---|
| | 623 | })); |
---|
| | 624 | }, this); |
---|
| | 625 | this.resolve(); |
---|
| | 626 | }, |
---|
| | 627 | // resolve the OCD media URLs |
---|
| | 628 | resolve: function() { |
---|
| | 629 | var self = this; |
---|
| | 630 | $('.ocd-item').each(function(idx, elem) { |
---|
| | 631 | var temp_arr = self.model[idx]._source.media_urls[0].url.split('/'); |
---|
| | 632 | var media_hash = temp_arr[temp_arr.length - 1]; |
---|
| | 633 | $.get('/resolve-ocd-media/'+ media_hash, function(resp) { |
---|
| | 634 | $(elem).find('img').attr('src', resp); |
---|
| | 635 | }); |
---|
| | 636 | }); |
---|
| | 637 | }, |
---|
| | 638 | onClickImg: function(event) { |
---|
| | 639 | event.preventDefault(); |
---|
| | 640 | // TODO: init the image anno |
---|
| | 641 | var url = $(event.currentTarget).find('img').attr('src'); |
---|
| | 642 | swtr.appView.loadURL(url); |
---|
| | 643 | return false; |
---|
| | 644 | } |
---|
| | 645 | }); |
---|
| | 646 | |
---|
558 | var HelpView = Backbone.View.extend({ | 647 | var HelpView = Backbone.View.extend({ |
---|
559 | el: $('#helpview'), | 648 | el: $('#helpview'), |
---|
560 | events: { | 649 | events: { |
---|
… | | … | |
---|
678 | case 9: text = 'You have to be <i>signed in</i> to sweet store to post sweets'; | 678 | case 9: text = 'You have to be <i>signed in</i> to sweet store to post sweets'; |
---|
679 | break; | 679 | break; |
---|
680 | case 10: text = 'Oops! Something went wrong. We couldn\'t publish the sweets. Try again.' | 680 | case 10: text = 'Oops! Something went wrong. We couldn\'t publish the sweets. Try again.' |
---|
| | 681 | break; |
---|
| | 682 | case 11: text = 'Search in <a href="http://www.opencultuurdata.nl/">Open Cuultur Data API</a>'; |
---|
681 | break; | 683 | break; |
---|
682 | } | 684 | } |
---|
683 | $(this.el).html(text); | 685 | $(this.el).html(text); |
---|
| | | | 3 | <head> | 3 | <head> |
---|
4 | <meta charset="utf-8"> | 4 | <meta charset="utf-8"> |
---|
5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | 5 | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
---|
6 | <title>swtr - the default sweet web app</title> | | <title>swtr - the default sweet web app</title> |
---|
| | 6 | <title> swtr - the canonical sweet web app </title> | 7 | | 7 | |
---|
8 | <meta name="description" content="Sweet Maker, Social, Semantic, Web, Decentralized, Makes Sweet, Sweet Swagger"> | | <meta name="description" content="Sweet Maker, Social, Semantic, Web, Decentralized, Makes Sweet, Sweet Swagger"> |
---|
| | 8 | <meta name="description" content="Sweet Maker, Social, Semantic, Web, Decentralized, Makes Sweet, Sweet Swagger, Swtr, swtr"> | 9 | <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet"> | 9 | <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet"> |
---|
10 | <link href="{{ url_for('static', filename='css/bootstrap-theme.min.css') }}" rel="stylesheet"> | 10 | <link href="{{ url_for('static', filename='css/bootstrap-theme.min.css') }}" rel="stylesheet"> |
---|
11 | <link href="{{ url_for('static', filename='css/annotorious.css') }}" rel="stylesheet"> | 11 | <link href="{{ url_for('static', filename='css/annotorious.css') }}" rel="stylesheet"> |
---|
12 | <link href="{{ url_for('static', filename='css/swtmaker.css') }}" rel="stylesheet"> | 12 | <link href="{{ url_for('static', filename='css/swtmaker.css') }}" rel="stylesheet"> |
---|
13 | <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-tags.css') }}" type="text/css" media="screen" /> | | <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap-tags.css') }}" type="text/css" media="screen" /> |
---|
| | 13 | <link href="{{ url_for('static', filename='css/bootstrap-tags.css') }}" rel="stylesheet"> | 14 | </head> | 14 | </head> |
---|
15 | | 15 | |
---|
16 | <body> | 16 | <body> |
---|
… | | … | |
---|
36 | <div class="col-md-8"> | 36 | <div class="col-md-8"> |
---|
37 | <form class="form-inline" role="form"> | 37 | <form class="form-inline" role="form"> |
---|
38 | <div class="form-group col-md-11"> | 38 | <div class="form-group col-md-11"> |
---|
39 | <label class="sr-only" for="img-url-input">Enter URL of the image</label> | | <label class="sr-only" for="img-url-input">Enter URL of the image</label> |
---|
| | 39 | <label class="sr-only" for="user-input">Enter URL of an image or web page</label> | 40 | <input class="form-control" type="text" | 40 | <input class="form-control" type="text" |
---|
41 | placeholder="Enter URL of the image or web page" id="img-url-input"> | | placeholder="Enter URL of the image or web page" id="img-url-input"> |
---|
| | 41 | placeholder="Enter URL of an image or web page" id="user-input"> | 42 | </div> | 42 | </div> |
---|
43 | <button type="submit" class="btn btn-primary" id="img-url-load">Load</button> | | <button type="submit" class="btn btn-primary" id="img-url-load">Load</button> |
---|
| | 43 | <button type="submit" class="btn btn-primary" id="user-input-submit">Load</button> | 44 | </form> | 44 | </form> |
---|
45 | </div> | 45 | </div> |
---|
46 | <div class="col-md-4"> | 46 | <div class="col-md-4"> |
---|
47 | </div> | 47 | </div> |
---|
48 | </div> <!-- end second row --> | 48 | </div> <!-- end second row --> |
---|
49 | <!-- third row - control panel? --> | 49 | <!-- third row - control panel? --> |
---|
50 | <div class="row"> | | <div class="row"> |
---|
51 | <div class="col-md-3"> | | <div class="col-md-3"> |
---|
52 | <input id="setbox" type="checkbox"/> | | <input id="setbox" type="checkbox"/> |
---|
53 | <label id="setcontrol" for="setbox">Show annotated areas</label> | | <label id="setcontrol" for="setbox">Show annotated areas</label> |
---|
| | 50 | <div class="row" id="control-panel"> | | | 51 | <div class="col-md-8"> |
---|
| | 52 | <form class="form-inline" role="form"> |
---|
| | 53 | <div class="form-group"> |
---|
| | 54 | <label class="checkbox-inline"> |
---|
| | 55 | <input type="checkbox" id="setbox"> Show annotated areas |
---|
| | 56 | </label> |
---|
| | 57 | </div> |
---|
| | 58 | <div class="form-group"> |
---|
| | 59 | <label class="checkbox-inline"> |
---|
| | 60 | <input type="checkbox" id="ocd-source"> Search in Open Cuultur Data |
---|
| | 61 | </label> |
---|
| | 62 | </div> |
---|
| | 63 | <div class="form-group"> |
---|
| | 64 | <button class="btn btn-default" id="sweet">Sweet</button> |
---|
| | 65 | </div> |
---|
| | 66 | </form> |
---|
54 | </div> | 67 | </div> |
---|
55 | <div class="col-md-1"> | | <div class="col-md-1"> |
---|
56 | <button class="btn btn-default" id="sweet">Sweet</button> | | <button class="btn btn-default" id="sweet">Sweet</button> |
---|
57 | </div> | | </div> |
---|
| | 68 | <div class="col-md-4"></div> | 58 | </div> <!-- end third row -- > | 69 | </div> <!-- end third row -- > |
---|
59 | <!-- fourth row: the image annotation window --> | 70 | <!-- fourth row: the image annotation window --> |
---|
60 | <div class="row"> | 71 | <div class="row"> |
---|
… | | … | |
---|
76 | <img src="" id="annotatable-img" class="img-responsive"> | 76 | <img src="" id="annotatable-img" class="img-responsive"> |
---|
77 | {% endif %} | 77 | {% endif %} |
---|
78 | </div> | 78 | </div> |
---|
| | 79 | <div id="ocd-results"></div> |
---|
79 | </div> <!-- end fourth row --> | 80 | </div> <!-- end fourth row --> |
---|
80 | | 81 | |
---|
81 | <div id="sweet-list-wrapper"> | 82 | <div id="sweet-list-wrapper"> |
---|
… | | … | |
---|
134 | <option value="link">Link</option> | 134 | <option value="link">Link</option> |
---|
135 | </select> | 135 | </select> |
---|
136 | </script> | 136 | </script> |
---|
137 | <!-- script type="text/template" id="dropdown-template"> | | <!-- script type="text/template" id="dropdown-template"> |
---|
138 | <form class="form-control" id="custom-dropdown"> | | <form class="form-control" id="custom-dropdown"> |
---|
139 | <textarea class="annotorious-editor-text goog-textarea" | | <textarea class="annotorious-editor-text goog-textarea" |
---|
140 | placeholder="Add Label" id="label"></textarea> | | placeholder="Add Label" id="label"></textarea> |
---|
141 | <textarea class="annotorious-editor-text goog-textarea" | | <textarea class="annotorious-editor-text goog-textarea" |
---|
142 | placeholder="Add Tags" id="tags"></textarea> | | placeholder="Add Tags" id="tags"></textarea> |
---|
143 | <textarea class="annotorious-editor-text goog-textarea" | | <textarea class="annotorious-editor-text goog-textarea" |
---|
144 | placeholder="Add Links" id="links"></textarea> | | placeholder="Add Links" id="links"></textarea> |
---|
145 | </form> | | </form> |
---|
146 | </script--> | | </script--> |
---|
147 | <script type="text/template" id="popup-template"> | 137 | <script type="text/template" id="popup-template"> |
---|
148 | <span class="annotorious-popup-text"> | 138 | <span class="annotorious-popup-text"> |
---|
149 | <ul class="custom-style-popup"> | 139 | <ul class="custom-style-popup"> |
---|
… | | … | |
---|
143 | <li class="custom-popup-line"><span>Related Links: </span><%= Links %></li> | 143 | <li class="custom-popup-line"><span>Related Links: </span><%= Links %></li> |
---|
144 | </ul> | 144 | </ul> |
---|
145 | </span> | 145 | </span> |
---|
| | 146 | </script> |
---|
| | 147 | <script type="text/template" id="ocd-item-template"> |
---|
| | 148 | <div class="col-sm-6 col-md-4 ocd-item"> |
---|
| | 149 | <h4> <%= title %> </h4> |
---|
| | 150 | <div class="media"> |
---|
| | 151 | <a href="<%= media_url %>"> |
---|
| | 152 | <img src="" class="responsive thumb-image"> |
---|
| | 153 | </a> |
---|
| | 154 | </div> |
---|
| | 155 | <div>Authors: <%= authors %> </div> |
---|
| | 156 | </div> |
---|
146 | </script> | 157 | </script> |
---|
147 | </body> | 158 | </body> |
---|
148 | </html> | 159 | </html> |
---|