Commit 83fde84d2afb6e93b76213340269d7fa91c5b63c
Improvements in the image annotation from OCD results
- Now client side is more intelligent in loading image from OCD search
results for annotation. Also, an endpoint in the server is available to
check the resource type of a URL. The loadURL function can be told explicitly
what type of resource it has to load for annotation. If it is not told, it
tries to find out by various means.
| | | | 85 | # takes in `query`, `size`, and `from` parameters in query string | 85 | # takes in `query`, `size`, and `from` parameters in query string |
---|
86 | # returns a JSON response | 86 | # returns a JSON response |
---|
87 | @app.route('/search/ocd', methods=['GET']) | 87 | @app.route('/search/ocd', methods=['GET']) |
---|
88 | def search_ocd(): | | def search_ocd(): |
---|
| | 88 | def searchOCD(): | 89 | query = flask.request.args.get('query') | 89 | query = flask.request.args.get('query') |
---|
90 | #collection = flask.request.args.get('collection') | 90 | #collection = flask.request.args.get('collection') |
---|
91 | size = flask.request.args.get('size') or 10 | 91 | size = flask.request.args.get('size') or 10 |
---|
… | | … | |
---|
117 | | 117 | |
---|
118 | | 118 | |
---|
119 | # resolve OCD Media URLs: http://docs.opencultuurdata.nl/user/api.html#resolver | 119 | # resolve OCD Media URLs: http://docs.opencultuurdata.nl/user/api.html#resolver |
---|
120 | @app.route('/resolve-ocd-media/<media_hash>', methods=['GET']) | | @app.route('/resolve-ocd-media/<media_hash>', methods=['GET']) |
---|
121 | def resolve_ocd_media_urls(media_hash): | | def resolve_ocd_media_urls(media_hash): |
---|
| | 120 | @app.route('/resolve-ocd-media', methods=['GET']) | | | 121 | def resolveOCDMediaURLs(): |
---|
122 | | 122 | |
---|
| | 123 | media_hash = flask.request.args.get('hash') or None |
---|
| | 124 | |
---|
| | 125 | if not media_hash: |
---|
| | 126 | flask.abort(400) |
---|
| | 127 | |
---|
123 | resp = requests.get('http://api.opencultuurdata.nl/v0/resolve/' + | 128 | resp = requests.get('http://api.opencultuurdata.nl/v0/resolve/' + |
---|
124 | media_hash) | 129 | media_hash) |
---|
125 | | 130 | |
---|
126 | response = flask.make_response() | | response = flask.make_response() |
---|
127 | response.data = resp.url | | response.data = resp.url |
---|
128 | return response | | return response |
---|
| | 131 | return flask.jsonify(url=resp.url) | 129 | | 132 | |
---|
130 | | 133 | |
---|
| | 134 | @app.route('/media-type', methods=['GET']) |
---|
| | 135 | def getMediaType(): |
---|
| | 136 | |
---|
| | 137 | where = flask.request.args.get('where') or None |
---|
| | 138 | |
---|
| | 139 | if not where: |
---|
| | 140 | flask.abort(400) |
---|
| | 141 | |
---|
| | 142 | resp = requests.get(where) |
---|
| | 143 | content = resp.text |
---|
| | 144 | |
---|
| | 145 | if imghdr.what('ignore', content) is None: |
---|
| | 146 | return flask.jsonify({'type': 'html'}) |
---|
| | 147 | else: |
---|
| | 148 | return flask.jsonify({'type': 'image'}) |
---|
| | 149 | |
---|
| | 150 | |
---|
131 | @app.route('/annotate', methods=['GET']) | 151 | @app.route('/annotate', methods=['GET']) |
---|
132 | def annotate(): | 152 | def annotate(): |
---|
133 | # img = urllib2.urlopen(flask.request.args['where']).read() | 153 | # img = urllib2.urlopen(flask.request.args['where']).read() |
---|
… | | … | |
---|
239 | style.set("rel", "stylesheet") | 239 | style.set("rel", "stylesheet") |
---|
240 | style.set("type", "text/css") | 240 | style.set("type", "text/css") |
---|
241 | | 241 | |
---|
242 | | | |
---|
243 | @app.route('/getMediaType') | | @app.route('/getMediaType') |
---|
244 | def getMediaType(): | | def getMediaType(): |
---|
245 | request = requests.get(flask.request.args['where']) | | request = requests.get(flask.request.args['where']) |
---|
246 | content = request.text | | content = request.text |
---|
247 | if imghdr.what('ignore', content) is None: | | if imghdr.what('ignore', content) is None: |
---|
248 | return flask.jsonify({'type': 'html'}) | | return flask.jsonify({'type': 'html'}) |
---|
249 | else: | | else: |
---|
250 | return flask.jsonify({'type': 'image'}) | | return flask.jsonify({'type': 'image'}) |
---|
251 | | 242 | |
---|
252 | # if the app is run directly from command-line | 243 | # if the app is run directly from command-line |
---|
253 | # assume its being run locally in a dev environment | 244 | # assume its being run locally in a dev environment |
---|
| | | | 306 | this.loadURL(input); | 306 | this.loadURL(input); |
---|
307 | } | 307 | } |
---|
308 | }, | 308 | }, |
---|
309 | loadURL: function(url) { | | loadURL: function(url) { |
---|
310 | $('#ocd-results').hide(); | | $('#ocd-results').hide(); |
---|
| | 309 | loadURL: function(url, type) { | | | 310 | console.log('loadURL()'); |
---|
| | 311 | if(this.source !== 'ocd') { |
---|
| | 312 | $('#ocd-results').hide(); |
---|
| | 313 | } |
---|
311 | $('#img-annotation-wrapper').show(); | 314 | $('#img-annotation-wrapper').show(); |
---|
312 | if(!url) { | 315 | if(!url) { |
---|
313 | return false; | 316 | return false; |
---|
314 | } | 317 | } |
---|
315 | // if image url then load the image annotation | | // if image url then load the image annotation |
---|
| | 318 | // if type is given explicitly; we load it as such. | | | 319 | if(type === 'image') { |
---|
| | 320 | this.setImage(url); |
---|
| | 321 | return false; |
---|
| | 322 | } |
---|
| | 323 | // else try to find what resource is the URL.. |
---|
| | 324 | // if url has an image extension then load the image annotation |
---|
316 | if(url.match(/.jpg|.jpeg|.png|.gif|.bmp|.svg/)) { | 325 | if(url.match(/.jpg|.jpeg|.png|.gif|.bmp|.svg/)) { |
---|
317 | | | |
---|
318 | this.imgURL = url; | | this.imgURL = url; |
---|
319 | | | |
---|
320 | if(this.$img.attr('src') === this.imgURL) { | | if(this.$img.attr('src') === this.imgURL) { |
---|
321 | return; | | return; |
---|
322 | } | | } |
---|
323 | anno.reset(); | | anno.reset(); |
---|
324 | var self = this; | | var self = this; |
---|
325 | this.$overlay.show(); | | this.$overlay.show(); |
---|
326 | this.helpview.step(7); | | this.helpview.step(7); |
---|
327 | this.$img.attr('src', this.imgURL); | | this.$img.attr('src', this.imgURL); |
---|
| | 326 | this.setImage(url); | 328 | return false; | 327 | return false; |
---|
329 | } | 328 | } |
---|
330 | // else load text annotation | | // else load text annotation |
---|
| | 329 | // else check with our /media-type endpoint to see what type of resource | | | 330 | // it is |
---|
331 | else { | 331 | else { |
---|
332 | window.location.href = '/annotate?where=' + url; | | window.location.href = '/annotate?where=' + url; |
---|
| | 332 | this.helpview.step(12); | | | 333 | this.$overlay.show(); |
---|
| | 334 | var self = this; |
---|
| | 335 | $.get('/media-type', {where: url}, function(response) { |
---|
| | 336 | //console.log(response); |
---|
| | 337 | self.$overlay.hide(); |
---|
| | 338 | if(response.type === 'image') { |
---|
| | 339 | self.setImage(url); |
---|
| | 340 | } |
---|
| | 341 | else { |
---|
| | 342 | window.location.href = '/annotate?where=' + url; |
---|
| | 343 | } |
---|
| | 344 | }); |
---|
333 | } | 345 | } |
---|
334 | }, | 346 | }, |
---|
| | 347 | setImage: function(url) { |
---|
| | 348 | this.imgURL = url; |
---|
| | 349 | |
---|
| | 350 | if(this.$img.attr('src') === this.imgURL) { |
---|
| | 351 | return; |
---|
| | 352 | } |
---|
| | 353 | anno.reset(); |
---|
| | 354 | var self = this; |
---|
| | 355 | this.$overlay.show(); |
---|
| | 356 | this.helpview.step(7); |
---|
| | 357 | this.$img.attr('src', this.imgURL); |
---|
| | 358 | }, |
---|
335 | imageLoaded: function(event) { | 359 | imageLoaded: function(event) { |
---|
336 | var self = event.data; | 360 | var self = event.data; |
---|
337 | console.log('image loaded'); | 361 | console.log('image loaded'); |
---|
… | | … | |
---|
635 | var $row_el; | 635 | var $row_el; |
---|
636 | this.$el.html(''); | 636 | this.$el.html(''); |
---|
637 | _.each(this.model, function(item, idx) { | 637 | _.each(this.model, function(item, idx) { |
---|
| | 638 | // put every 3 items in a row |
---|
638 | if(idx % 3 === 0) { | 639 | if(idx % 3 === 0) { |
---|
639 | $row_el = $('<div class="row"></div>'); | 640 | $row_el = $('<div class="row"></div>'); |
---|
640 | this.$el.append($row_el); | 641 | this.$el.append($row_el); |
---|
… | | … | |
---|
646 | authors: item._source.authors | 646 | authors: item._source.authors |
---|
647 | })); | 647 | })); |
---|
648 | }, this); | 648 | }, this); |
---|
649 | this.resolve(); | | this.resolve(); |
---|
| | 649 | this.resolveOCDURLs(); | 650 | }, | 650 | }, |
---|
651 | // resolve the OCD media URLs | 651 | // resolve the OCD media URLs |
---|
652 | resolve: function() { | | resolve: function() { |
---|
| | 652 | resolveOCDURLs: function() { | 653 | var self = this; | 653 | var self = this; |
---|
654 | $('.ocd-item').each(function(idx, elem) { | 654 | $('.ocd-item').each(function(idx, elem) { |
---|
655 | var temp_arr = self.model[idx]._source.media_urls[0].url.split('/'); | 655 | var temp_arr = self.model[idx]._source.media_urls[0].url.split('/'); |
---|
656 | var media_hash = temp_arr[temp_arr.length - 1]; | 656 | var media_hash = temp_arr[temp_arr.length - 1]; |
---|
657 | $.get('/resolve-ocd-media/'+ media_hash, function(resp) { | | $.get('/resolve-ocd-media/'+ media_hash, function(resp) { |
---|
658 | $(elem).find('img').attr('src', resp); | | $(elem).find('img').attr('src', resp); |
---|
| | 657 | $.get('/resolve-ocd-media', {hash: media_hash}, function(resp) { | | | 658 | $(elem).find('img').attr('src', resp.url); |
---|
659 | }); | 659 | }); |
---|
660 | }); | 660 | }); |
---|
661 | }, | 661 | }, |
---|
… | | … | |
---|
663 | event.preventDefault(); | 663 | event.preventDefault(); |
---|
664 | // TODO: init the image anno | 664 | // TODO: init the image anno |
---|
665 | var url = $(event.currentTarget).find('img').attr('src'); | 665 | var url = $(event.currentTarget).find('img').attr('src'); |
---|
666 | swtr.appView.loadURL(url); | | swtr.appView.loadURL(url); |
---|
| | 666 | swtr.appView.loadURL(url, 'image'); | 667 | return false; | 667 | return false; |
---|
668 | } | 668 | } |
---|
669 | }); | 669 | }); |
---|
… | | … | |
---|
682 | var text = ''; | 682 | var text = ''; |
---|
683 | switch (n) { | 683 | switch (n) { |
---|
684 | case 0 : text = 'Getting annotations..'; | 684 | case 0 : text = 'Getting annotations..'; |
---|
685 | break; | | break; |
---|
| | 685 | break; | 686 | case 1: text = 'Enter the URL of an image or web page below, and start annotating!'; | 686 | case 1: text = 'Enter the URL of an image or web page below, and start annotating!'; |
---|
687 | break; | | break; |
---|
| | 687 | break; | 688 | case 2: text = 'Annotate the image, or see other annotations'; | 688 | case 2: text = 'Annotate the image, or see other annotations'; |
---|
689 | break; | | break; |
---|
| | 689 | break; | 690 | case 3: text = 'Now you can sweet this annotation, or add more annotations'; | 690 | case 3: text = 'Now you can sweet this annotation, or add more annotations'; |
---|
691 | break; | | break; |
---|
| | 691 | break; | 692 | case 4: text = 'Click Sweet button to publish these annotations to the Sweet Store'; | 692 | case 4: text = 'Click Sweet button to publish these annotations to the Sweet Store'; |
---|
693 | break; | | break; |
---|
| | 693 | break; | 694 | case 5: text = 'Publishing your sweets'; | 694 | case 5: text = 'Publishing your sweets'; |
---|
695 | break; | | break; |
---|
| | 695 | break; | 696 | case 6: text = 'Sweets successfully posted'; | 696 | case 6: text = 'Sweets successfully posted'; |
---|
697 | break; | | break; |
---|
| | 697 | break; | 698 | case 7: text = 'Fetching your image..'; | 698 | case 7: text = 'Fetching your image..'; |
---|
699 | break; | | break; |
---|
| | 699 | break; | 700 | case 8: text = 'Oops! Seems like the image URL is wrong! Or we couldn\'t fetch the image.'; | 700 | case 8: text = 'Oops! Seems like the image URL is wrong! Or we couldn\'t fetch the image.'; |
---|
701 | break; | | break; |
---|
| | 701 | break; | 702 | case 9: text = 'You have to be <i>signed in</i> to sweet store to post sweets'; | 702 | case 9: text = 'You have to be <i>signed in</i> to sweet store to post sweets'; |
---|
703 | break; | | break; |
---|
| | 703 | break; | 704 | case 10: text = 'Oops! Something went wrong. We couldn\'t publish the sweets. Try again.' | 704 | case 10: text = 'Oops! Something went wrong. We couldn\'t publish the sweets. Try again.' |
---|
705 | break; | | break; |
---|
| | 705 | break; | 706 | case 11: text = 'Search in <a href="http://www.opencultuurdata.nl/">Open Cuultur Data API</a>'; | 706 | case 11: text = 'Search in <a href="http://www.opencultuurdata.nl/">Open Cuultur Data API</a>'; |
---|
707 | break; | | break; |
---|
| | 707 | break; | | | 708 | case 12: text = 'Analyzing the resource type..'; |
---|
| | 709 | break; |
---|
708 | } | 710 | } |
---|
709 | $(this.el).html(text); | 711 | $(this.el).html(text); |
---|
710 | $(window).scrollTop(0, 0); | 712 | $(window).scrollTop(0, 0); |
---|
| | | | 71 | <div class="row"> | 71 | <div class="row"> |
---|
72 | <div id="img-annotation-wrapper" class="col-md-12 col-xs-12 col-lg-12 col-sm-12 well"> | 72 | <div id="img-annotation-wrapper" class="col-md-12 col-xs-12 col-lg-12 col-sm-12 well"> |
---|
73 | {% if url %} | 73 | {% if url %} |
---|
74 | <img src="{{ url }}" id="annotatable-img" class="img-responsive"> | | <img src="{{ url }}" id="annotatable-img" class="img-responsive"> |
---|
| | 74 | <img src="{{ url }}" id="annotatable-img" class="img-responsive" alt="Annotation Workbench"> | 75 | {% else %} | 75 | {% else %} |
---|
76 | <img src="" id="annotatable-img" class="img-responsive"> | | <img src="" id="annotatable-img" class="img-responsive"> |
---|
| | 76 | <img src="" id="annotatable-img" class="img-responsive" alt="Annotation Workbench"> | 77 | {% endif %} | 77 | {% endif %} |
---|
78 | </div> | 78 | </div> |
---|
79 | <div id="ocd-results"></div> | 79 | <div id="ocd-results"></div> |
---|