diff --git a/js/src/annotations/osd-region-draw-tool.js b/js/src/annotations/osd-region-draw-tool.js index a86f1033f6982ee08864acd5ec424ac753ab883a..ac7e01305517e90f5f2ffc01543769e483aeab07 100644 --- a/js/src/annotations/osd-region-draw-tool.js +++ b/js/src/annotations/osd-region-draw-tool.js @@ -109,6 +109,8 @@ if (shapeArray.length > 0) { _this.svgOverlay.restoreLastView(shapeArray); _this.annotationsToShapesMap[annotation['@id']] = shapeArray; + } else { + console.log("ERROR couldn't find a strategy for " + annotation["@id"]); } } catch(e) { console.log('ERROR OsdRegionDrawTool#render anno:', annotation, 'error:', e); diff --git a/js/src/annotations/simpleASEndpoint.js b/js/src/annotations/simpleASEndpoint.js index 1c2cdd218a242b7c166b4b8ab3ec480701907f18..854ed532d4303beb505904654f439296b3bae828 100644 --- a/js/src/annotations/simpleASEndpoint.js +++ b/js/src/annotations/simpleASEndpoint.js @@ -1,12 +1,12 @@ /* - * Edited version of https://github.com/IIIF/mirador/blob/9e3c6bbb894e044d01ad51aae1b70309939de5a9/js/src/annotations/catchEndpoint.js - * This module tries to store the annotation as is in a RDF store but some fiddeling is required. Fidles are: - * + * Edited version of https://github.com/IIIF/mirador/blob/9e3c6bbb894e044d01ad51aae1b70309939de5a9/js/src/annotations/catchEndpoint.js + * This module tries to store the annotation as is in a RDF store but some fiddeling is required. + * Fidles are: * - delete annotation fails if id has a / in it so have to send sanatised ids to mirador * - mirador requires an endpoint variable in the annotation pointing to this class. - * + * * Note: this endpoint doesn't currently support authentication, just returns allow all - * + * * All Endpoints need to have at least the following: * annotationsList - current list of OA Annotations * dfd - Deferred Object @@ -15,182 +15,211 @@ * create(oaAnnotation, returnSuccess, returnError) * update(oaAnnotation, returnSuccess, returnError) * deleteAnnotation(annotationID, returnSuccess, returnError) (delete is a reserved word) - * TODO: - * There is a bug in that if you create an annotation and then delete it (without moving pages) then click either the write annotation button - * or try to create a new annotation the deleted annotation re-appears. Changing pages fixes the issue as the annoation is delete from the annotation store * */ -(function($){ +(function ($){ - $.SimpleASEndpoint = function(options) { +$.SimpleASEndpoint = function (options) { - jQuery.extend(this, { - token: null, - // prefix: 'annotation', /**/ - uri: null, - url: options.url, - dfd: null, - annotationsList: [], //OA list for Mirador use - idMapper: {} // internal list for module use to map id to URI + jQuery.extend(this, { + token: null, + // prefix: 'annotation', /**/ + uri: null, + url: options.url, + dfd: null, + // OA list for Mirador use + annotationsList: [], + // internal list for module use to map id to URI + idMapper: {} }, options); this.init(); }; $.SimpleASEndpoint.prototype = { - //Any set up for this endpoint, and triggers a search of the URI passed to object - init: function() { + // Any set up for this endpoint, and triggers a search of the URI passed to object + init: function () { this.catchOptions = { user: { - id: this.userid, + id: this.userid, name: this.username }, permissions: { 'read': [], 'update': [this.userid], 'delete': [this.userid], - 'admin': [this.userid] + 'admin': [this.userid] } }; }, - //Search endpoint for all annotations with a given URI - search: function(options, successCallback, errorCallback) { + // Search endpoint for all annotations with a given URI + search: function (options, successCallback, errorCallback) { var _this = this; - this.annotationsList = []; //clear out current list + this.annotationsList = []; // clear out current list jQuery.ajax({ - url: _this.url + "/search", // this.prefix+ + url: _this.url + '/search', // this.prefix+ cache: false, type: 'GET', dataType: 'json', headers: { - //"x-annotator-auth-token": this.token + // 'x-annotator-auth-token': this.token }, data: { uri: options.uri, APIKey: _this.APIKey, - media: "image", + media: 'image', limit: 10000 }, - contentType: "application/json; charset=utf-8", + contentType: 'application/json; charset=utf-8', success: function(data) { - if (typeof successCallback === "function") { + _this.annotationsList = data; // gmr + jQuery.each(_this.annotationsList, function(index, value) { + // Swap out URI of anno to shorter ID + value.fullId = value['@id']; + value['@id'] = $.genUUID(); + _this.idMapper[value['@id']] = value.fullId; + value.endpoint = _this; + // Ensure on is an array + _this.fixOn(value); + }); + if (typeof successCallback === 'function') { successCallback(data); } else { - _this.annotationsList = data; // gmr - jQuery.each(_this.annotationsList, function(index, value) { - value.fullId = value["@id"]; - value["@id"] = $.genUUID(); - _this.idMapper[value["@id"]] = value.fullId; - value.endpoint = _this; - }); - _this.dfd.resolve(false); + _this.dfd.resolve(true); } }, - error: function() { - if (typeof errorCallback === "function") { + error: function(xhr, statusText, err) { + if (typeof errorCallback === 'function') { errorCallback(); } else { - console.log("The request for annotations has caused an error for endpoint: "+ options.uri); + _this.dfd.reject(); + console.log('The request for annotations has caused an error for endpoint: ' + options.uri + ' due to ' + statusText); } } }); }, - deleteAnnotation: function(annotationID, returnSuccess, returnError) { + fixOn: function (annotation) { + var oldOn; + if (annotation && annotation.on && !jQuery.isArray(annotation.on) && annotation.on.selector && annotation.on.selector.default) { + oldOn = annotation.on; + annotation.on = [oldOn]; + } + }, + + deleteAnnotation: function (annotationID, returnSuccess, returnError) { var _this = this; jQuery.ajax({ - url: _this.url + "/destroy?uri=" + encodeURIComponent(_this.idMapper[annotationID]) + "&APIKey=" + _this.APIKey, // this.prefix+ + url: _this.url + '/destroy?uri=' + encodeURIComponent(_this.idMapper[annotationID]) + '&APIKey=' + _this.APIKey, // this.prefix+ type: 'DELETE', dataType: 'json', headers: { - //"x-annotator-auth-token": this.token + // 'x-annotator-auth-token': this.token }, data: { uri: annotationID, }, - contentType: "application/json; charset=utf-8", + contentType: 'application/json; charset=utf-8', success: function(data) { - returnSuccess(); + if (typeof returnSuccess === 'function') { + returnSuccess(); + } }, - error: function() { - returnError(); + error: function(xhr, statusText, err) { + if (typeof returnError === 'function') { + returnError(); + } else { + console.log('Failed to delete annotation ' + annotationID + ' due to ' + statusText); + } } }); }, - update: function(oaAnnotation, returnSuccess, returnError) { - var annotation = oaAnnotation, - _this = this; + update: function (oaAnnotation, returnSuccess, returnError) { + var annotation = oaAnnotation; + var _this = this; // slashes don't work in JQuery.find which is used for delete // so need to switch http:// id to full id and back again for delete. - shortId = annotation["@id"]; - annotation["@id"] = annotation.fullId; - annotationID = annotation.fullId;//annotation["@id"]; + var shortId = annotation['@id']; + var annotationID = annotation.fullId;// annotation['@id']; + annotation['@id'] = annotation.fullId; delete annotation.fullId; delete annotation.endpoint; jQuery.ajax({ - url: _this.url + "/update/"+encodeURIComponent(annotationID) + "?APIKey=" + _this.APIKey, //this.prefix+ + url: _this.url + '/update/' + encodeURIComponent(annotationID) + '?APIKey=' + _this.APIKey, // this.prefix+ type: 'POST', dataType: 'json', headers: { - //"x-annotator-auth-token": this.token + // 'x-annotator-auth-token': this.token }, data: JSON.stringify(annotation), - contentType: "application/json; charset=utf-8", + contentType: 'application/json; charset=utf-8', success: function(data) { - /* this returned data doesn't seem to be used anywhere */ - returnSuccess(); + _this.fixOn(data); + if (typeof returnSuccess === 'function') { + returnSuccess(data); + } }, - error: function() { - returnError(); + error: function(xhr, statusText, err) { + if (typeof returnError === 'function') { + returnError(); + } else { + console.log('Failed to update annotation: ' + oaAnnotation['@id'] + ' due to ' + statusText); + } } }); // this is what updates the viewer annotation.endpoint = _this; - annotation.fullId = annotation["@id"]; - annotation["@id"] = shortId; + annotation.fullId = annotation['@id']; + annotation['@id'] = shortId; }, - create: function(oaAnnotation, returnSuccess, returnError) { - var annotation = oaAnnotation, - _this = this; + create: function (oaAnnotation, returnSuccess, returnError) { + var annotation = oaAnnotation; + var _this = this; jQuery.ajax({ - url: _this.url + "/create?APIKey=" + _this.APIKey, //this.prefix+ + url: _this.url + '/create?APIKey=' + _this.APIKey, // this.prefix+ type: 'POST', dataType: 'json', headers: { - //"x-annotator-auth-token": this.token + // 'x-annotator-auth-token': this.token }, data: JSON.stringify(annotation), - contentType: "application/json; charset=utf-8", + contentType: 'application/json; charset=utf-8', success: function(data) { - data.fullId = data["@id"]; - data["@id"] = $.genUUID(); + data.fullId = data['@id']; + data['@id'] = $.genUUID(); data.endpoint = _this; - _this.idMapper[data["@id"]] = data.fullId; - - returnSuccess(data); + _this.idMapper[data['@id']] = data.fullId; + _this.fixOn(data); + if (typeof returnSuccess === 'function') { + returnSuccess(data); + } }, - error: function() { - returnError(); + error: function(xhr, statusText, err) { + if (typeof returnError === 'function') { + returnError(); + } else { + console.log('Failed to create annotation: ' + oaAnnotation['@id'] + ' due to ' + statusText); + } } }); }, - set: function(prop, value, options) { + set: function (prop, value, options) { if (options) { this[options.parent][prop] = value; } else { this[prop] = value; } }, - userAuthorize: function(action, annotation) { + userAuthorize: function (action, annotation) { return true; // allow all } }; diff --git a/spec/annotations/simple-as-endpoint.test.js b/spec/annotations/simple-as-endpoint.test.js index 8bb86c8ba0bac7180a96ece5290f6bac5c4f3a94..066b8a33a3864b2dfe9aa5e6a4bf2841ed5cb10f 100644 --- a/spec/annotations/simple-as-endpoint.test.js +++ b/spec/annotations/simple-as-endpoint.test.js @@ -75,7 +75,7 @@ describe('SimpleASEndpoint', function() { subject.search({uri: "http://sas.example.net"}); expect(successCallback).not.toHaveBeenCalled(); expect(errorCallback).not.toHaveBeenCalled(); - expect(console.log).toHaveBeenCalledWith("The request for annotations has caused an error for endpoint: http://sas.example.net"); + expect(console.log).toHaveBeenCalledWith("The request for annotations has caused an error for endpoint: http://sas.example.net due to undefined"); }); it('should run callback on failure if provided', function() { ajaxSuccess = false; @@ -208,4 +208,4 @@ describe('SimpleASEndpoint', function() { expect(subject.userAuthorize('admin', {})).toBe(true); }); }); -}); +});