Commit 005044c9 authored by Sean Hammond's avatar Sean Hammond

Merge pull request #3214 from hypothesis/295-remove-empty-annotations

Remove empty annotations when a new annotation is created
parents 7034741b d8db92c8
/* jshint node: true */ /* jshint node: true */
'use strict'; 'use strict';
var angular = require('angular');
var annotationMetadata = require('../annotation-metadata'); var annotationMetadata = require('../annotation-metadata');
var dateUtil = require('../date-util'); var dateUtil = require('../date-util');
var documentDomain = require('../filter/document-domain'); var documentDomain = require('../filter/document-domain');
...@@ -260,7 +262,11 @@ function AnnotationController( ...@@ -260,7 +262,11 @@ function AnnotationController(
// successfully saved to the server, and also when changes to the // successfully saved to the server, and also when changes to the
// annotation made by another client are received by this client from the // annotation made by another client are received by this client from the
// server. // server.
$rootScope.$on('annotationUpdated', onAnnotationUpdated); $rootScope.$on(events.ANNOTATION_UPDATED, onAnnotationUpdated);
// When a new annotation is created, remove any existing annotations that
// are empty
$rootScope.$on(events.BEFORE_ANNOTATION_CREATED, deleteIfNewAndEmpty);
// Call `onDestroy()` when this AnnotationController's scope is removed. // Call `onDestroy()` when this AnnotationController's scope is removed.
$scope.$on('$destroy', onDestroy); $scope.$on('$destroy', onDestroy);
...@@ -309,6 +315,12 @@ function AnnotationController( ...@@ -309,6 +315,12 @@ function AnnotationController(
} }
} }
function deleteIfNewAndEmpty() {
if (isNew(domainModel) && !vm.form.text && vm.form.tags.length === 0) {
vm.revert();
}
}
function onDestroy() { function onDestroy() {
if (vm.cancelTimestampRefresh) { if (vm.cancelTimestampRefresh) {
vm.cancelTimestampRefresh(); vm.cancelTimestampRefresh();
...@@ -363,7 +375,7 @@ function AnnotationController( ...@@ -363,7 +375,7 @@ function AnnotationController(
// Highlights are always private. // Highlights are always private.
domainModel.permissions = permissions.private(); domainModel.permissions = permissions.private();
domainModel.$create().then(function() { domainModel.$create().then(function() {
$rootScope.$emit('annotationCreated', domainModel); $rootScope.$emit(events.ANNOTATION_CREATED, domainModel);
updateView(domainModel); updateView(domainModel);
}); });
} else { } else {
...@@ -562,7 +574,7 @@ function AnnotationController( ...@@ -562,7 +574,7 @@ function AnnotationController(
vm.revert = function() { vm.revert = function() {
drafts.remove(domainModel); drafts.remove(domainModel);
if (vm.action === 'create') { if (vm.action === 'create') {
$rootScope.$emit('annotationDeleted', domainModel); $rootScope.$emit(events.ANNOTATION_DELETED, domainModel);
} else { } else {
updateView(domainModel); updateView(domainModel);
view(); view();
...@@ -597,7 +609,7 @@ function AnnotationController( ...@@ -597,7 +609,7 @@ function AnnotationController(
case 'create': case 'create':
updateDomainModel(domainModel, vm, permissions); updateDomainModel(domainModel, vm, permissions);
saved = domainModel.$create().then(function () { saved = domainModel.$create().then(function () {
$rootScope.$emit('annotationCreated', domainModel); $rootScope.$emit(events.ANNOTATION_CREATED, domainModel);
updateView(domainModel); updateView(domainModel);
drafts.remove(domainModel); drafts.remove(domainModel);
}); });
...@@ -610,7 +622,7 @@ function AnnotationController( ...@@ -610,7 +622,7 @@ function AnnotationController(
id: updatedModel.id id: updatedModel.id
}).then(function () { }).then(function () {
drafts.remove(domainModel); drafts.remove(domainModel);
$rootScope.$emit('annotationUpdated', updatedModel); $rootScope.$emit(events.ANNOTATION_UPDATED, updatedModel);
}); });
break; break;
......
...@@ -6,6 +6,7 @@ var proxyquire = require('proxyquire'); ...@@ -6,6 +6,7 @@ var proxyquire = require('proxyquire');
var events = require('../../events'); var events = require('../../events');
var fixtures = require('../../test/annotation-fixtures'); var fixtures = require('../../test/annotation-fixtures');
var testUtil = require('../../test/util');
var util = require('./util'); var util = require('./util');
var inject = angular.mock.inject; var inject = angular.mock.inject;
...@@ -17,6 +18,7 @@ function annotationDirective() { ...@@ -17,6 +18,7 @@ function annotationDirective() {
var noop = function () { return ''; }; var noop = function () { return ''; };
var annotation = proxyquire('../annotation', { var annotation = proxyquire('../annotation', {
angular: testUtil.noCallThru(angular),
'../filter/document-domain': noop, '../filter/document-domain': noop,
'../filter/document-title': noop, '../filter/document-title': noop,
'../filter/persona': { '../filter/persona': {
...@@ -1100,7 +1102,7 @@ describe('annotation', function() { ...@@ -1100,7 +1102,7 @@ describe('annotation', function() {
sandbox.spy($rootScope, '$emit'); sandbox.spy($rootScope, '$emit');
annotation.$create.returns(Promise.resolve()); annotation.$create.returns(Promise.resolve());
controller.save().then(function() { controller.save().then(function() {
assert($rootScope.$emit.calledWith('annotationCreated')); assert($rootScope.$emit.calledWith(events.ANNOTATION_CREATED));
done(); done();
}); });
} }
...@@ -1311,7 +1313,7 @@ describe('annotation', function() { ...@@ -1311,7 +1313,7 @@ describe('annotation', function() {
text: 'new text', text: 'new text',
}; };
$rootScope.$emit('annotationUpdated', updatedModel); $rootScope.$emit(events.ANNOTATION_UPDATED, updatedModel);
assert.equal(parts.controller.form.text, 'new text'); assert.equal(parts.controller.form.text, 'new text');
}); });
...@@ -1324,12 +1326,49 @@ describe('annotation', function() { ...@@ -1324,12 +1326,49 @@ describe('annotation', function() {
text: 'new text', text: 'new text',
}; };
$rootScope.$emit('annotationUpdated', updatedModel); $rootScope.$emit(events.ANNOTATION_UPDATED, updatedModel);
assert.equal(parts.controller.form.text, 'original text'); assert.equal(parts.controller.form.text, 'original text');
}); });
}); });
describe('when another new annotation is created', function () {
it('removes the current annotation if empty', function () {
var annotation = fixtures.newEmptyAnnotation();
createDirective(annotation);
$rootScope.$emit(events.BEFORE_ANNOTATION_CREATED,
fixtures.newAnnotation());
assert.calledWith(fakeDrafts.remove, annotation);
});
it('does not remove the current annotation if is is not new', function () {
var parts = createDirective(fixtures.defaultAnnotation());
parts.controller.form.text = '';
parts.controller.form.tags = [];
$rootScope.$emit(events.BEFORE_ANNOTATION_CREATED,
fixtures.newAnnotation());
assert.notCalled(fakeDrafts.remove);
});
it('does not remove the current annotation if it has text', function () {
var annotation = fixtures.newAnnotation();
var parts = createDirective(annotation);
parts.controller.form.text = 'An incomplete thought';
$rootScope.$emit(events.BEFORE_ANNOTATION_CREATED,
fixtures.newAnnotation());
assert.notCalled(fakeDrafts.remove);
});
it('does not remove the current annotation if it has tags', function () {
var annotation = fixtures.newAnnotation();
var parts = createDirective(annotation);
parts.controller.form.tags = [{text: 'a-tag'}];
$rootScope.$emit(events.BEFORE_ANNOTATION_CREATED,
fixtures.newAnnotation());
assert.notCalled(fakeDrafts.remove);
});
});
describe('onGroupFocused()', function() { describe('onGroupFocused()', function() {
it('if the annotation is being edited it updates drafts', function() { it('if the annotation is being edited it updates drafts', function() {
var parts = createDirective(); var parts = createDirective();
......
...@@ -30,6 +30,18 @@ function newAnnotation() { ...@@ -30,6 +30,18 @@ function newAnnotation() {
}; };
} }
/** Return a new annotation which has no tags or text. */
function newEmptyAnnotation() {
return {
id: undefined,
$highlight: undefined,
target: ['foo'],
references: [],
text: '',
tags: [],
};
}
/** Return an annotation domain model object for a new highlight /** Return an annotation domain model object for a new highlight
* (newly-created client-side, not yet saved to the server). * (newly-created client-side, not yet saved to the server).
*/ */
...@@ -97,6 +109,7 @@ function oldReply() { ...@@ -97,6 +109,7 @@ function oldReply() {
module.exports = { module.exports = {
defaultAnnotation: defaultAnnotation, defaultAnnotation: defaultAnnotation,
newAnnotation: newAnnotation, newAnnotation: newAnnotation,
newEmptyAnnotation: newEmptyAnnotation,
newHighlight: newHighlight, newHighlight: newHighlight,
oldAnnotation: oldAnnotation, oldAnnotation: oldAnnotation,
oldHighlight: oldHighlight, oldHighlight: oldHighlight,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment