Commit 124114ec authored by Sean Hammond's avatar Sean Hammond

Merge pull request #2966 from hypothesis/annotation-element-directive

Make annotation directive more consistent with other directives
parents e00042e4 151335a1
...@@ -254,11 +254,6 @@ function AnnotationController( ...@@ -254,11 +254,6 @@ function AnnotationController(
/** Whether or not this annotation is private. */ /** Whether or not this annotation is private. */
vm.isPrivate = false; vm.isPrivate = false;
/** Copy isSidebar from $scope onto vm for consistency (we want this
* directive's templates to always access variables from vm rather than
* directly from scope). */
vm.isSidebar = $scope.isSidebar;
/** A fuzzy, relative (eg. '6 days ago') format of the annotation's /** A fuzzy, relative (eg. '6 days ago') format of the annotation's
* last update timestamp * last update timestamp
*/ */
...@@ -290,7 +285,7 @@ function AnnotationController( ...@@ -290,7 +285,7 @@ function AnnotationController(
* haven't been saved yet - the data that will be saved to the server when * haven't been saved yet - the data that will be saved to the server when
* they are saved). * they are saved).
*/ */
domainModel = $scope.annotationGet(); domainModel = vm.annotation;
/** /**
* `true` if this AnnotationController instance was created as a result of * `true` if this AnnotationController instance was created as a result of
...@@ -811,17 +806,18 @@ function link(scope, elem, attrs, controllers) { ...@@ -811,17 +806,18 @@ function link(scope, elem, attrs, controllers) {
// @ngInject // @ngInject
function annotation($document) { function annotation($document) {
return { return {
restrict: 'E',
bindToController: true,
controller: AnnotationController, controller: AnnotationController,
controllerAs: 'vm', controllerAs: 'vm',
link: link, link: link,
require: ['annotation', '?^thread', '?^threadFilter', '?^deepCount'], require: ['annotation', '?^thread', '?^threadFilter', '?^deepCount'],
scope: { scope: {
annotationGet: '&annotation', annotation: '=',
// Indicates whether this is the last reply in a thread. // Indicates whether this is the last reply in a thread.
isLastReply: '=', isLastReply: '=',
replyCount: '@annotationReplyCount', replyCount: '=',
replyCountClick: '&annotationReplyCountClick', onReplyCountClick: '&',
showReplyCount: '@annotationShowReplyCount',
isSidebar: '=' isSidebar: '='
}, },
templateUrl: 'annotation.html' templateUrl: 'annotation.html'
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
var Promise = require('core-js/library/es6/promise'); var Promise = require('core-js/library/es6/promise');
var events = require('../../events'); var events = require('../../events');
var util = require('./util');
var module = angular.mock.module; var module = angular.mock.module;
var inject = angular.mock.inject; var inject = angular.mock.inject;
...@@ -423,17 +424,14 @@ describe('annotation', function() { ...@@ -423,17 +424,14 @@ describe('annotation', function() {
function createDirective(annotation) { function createDirective(annotation) {
annotation = annotation || defaultAnnotation(); annotation = annotation || defaultAnnotation();
$scope.annotation = annotation; var element = util.createDirective(document, 'annotation', {
var element = angular.element('<div annotation="annotation">'); annotation: annotation,
compileService()(element)($scope); });
$scope.$digest();
var controller = element.controller('annotation');
var scope = element.isolateScope();
return { return {
annotation: annotation, annotation: annotation,
controller: controller, controller: element.ctrl,
element: element, element: element,
scope: scope scope: element.scope,
}; };
} }
...@@ -948,11 +946,12 @@ describe('annotation', function() { ...@@ -948,11 +946,12 @@ describe('annotation', function() {
}); });
it('makes the annotation shared if the parent is shared', function() { it('makes the annotation shared if the parent is shared', function() {
var controller = createDirective(annotation).controller; var annotation = defaultAnnotation();
$scope.annotation.group = 'my group'; annotation.group = 'my group';
$scope.annotation.permissions = { annotation.permissions = {
read: ['my group'] read: ['my-group'],
}; };
var controller = createDirective(annotation).controller;
var reply = {}; var reply = {};
fakeAnnotationMapper.createAnnotation.returns(reply); fakeAnnotationMapper.createAnnotation.returns(reply);
fakePermissions.isShared = function(permissions, group) { fakePermissions.isShared = function(permissions, group) {
...@@ -982,12 +981,13 @@ describe('annotation', function() { ...@@ -982,12 +981,13 @@ describe('annotation', function() {
); );
it('sets the reply\'s group to be the same as its parent\'s', function() { it('sets the reply\'s group to be the same as its parent\'s', function() {
var annotation = defaultAnnotation();
annotation.group = 'my group';
var controller = createDirective(annotation).controller; var controller = createDirective(annotation).controller;
$scope.annotation.group = 'my group';
var reply = {}; var reply = {};
fakeAnnotationMapper.createAnnotation.returns(reply); fakeAnnotationMapper.createAnnotation.returns(reply);
controller.reply(); controller.reply();
assert.equal(reply.group, $scope.annotation.group); assert.equal(reply.group, annotation.group);
}); });
}); });
...@@ -1719,7 +1719,7 @@ describe('annotation', function() { ...@@ -1719,7 +1719,7 @@ describe('annotation', function() {
$provide.value('documentDomainFilter', locals.documentDomainFilter); $provide.value('documentDomainFilter', locals.documentDomainFilter);
$provide.value('localStorage', locals.localStorage); $provide.value('localStorage', locals.localStorage);
}); });
locals.element = angular.element('<div annotation="annotation">'); locals.element = angular.element('<annotation annotation="annotation">');
var compiledElement = compileService()(locals.element); var compiledElement = compileService()(locals.element);
locals.$rootScope = getRootScope(); locals.$rootScope = getRootScope();
locals.parentScope = locals.$rootScope.$new(); locals.parentScope = locals.$rootScope.$new();
......
...@@ -215,39 +215,6 @@ describe 'thread', -> ...@@ -215,39 +215,6 @@ describe 'thread', ->
count.withArgs('match').returns(1) count.withArgs('match').returns(1)
assert.isTrue(controller.shouldShowAsReply()) assert.isTrue(controller.shouldShowAsReply())
describe '#shouldShowNumReplies', ->
count = null
filterActive = false
beforeEach ->
createDirective()
count = sinon.stub()
controller.counter = {count: count}
controller.filter = {active: -> filterActive}
describe 'when not filtered', ->
it 'shows the reply if the thread has children', ->
count.withArgs('message').returns(1)
assert.isTrue(controller.shouldShowNumReplies())
it 'does not show the reply if the thread has no children', ->
count.withArgs('message').returns(0)
assert.isFalse(controller.shouldShowNumReplies())
describe 'when filtered with children', ->
beforeEach ->
filterActive = true
it 'shows the reply', ->
count.withArgs('match').returns(1)
count.withArgs('message').returns(1)
assert.isTrue(controller.shouldShowNumReplies())
it 'does not show the reply if the message count does not match the match count', ->
count.withArgs('match').returns(0)
count.withArgs('message').returns(1)
assert.isFalse(controller.shouldShowNumReplies())
describe '#numReplies', -> describe '#numReplies', ->
beforeEach -> beforeEach ->
......
...@@ -11,7 +11,7 @@ function hyphenate(name) { ...@@ -11,7 +11,7 @@ function hyphenate(name) {
* A helper for instantiating an AngularJS directive in a unit test. * A helper for instantiating an AngularJS directive in a unit test.
* *
* Usage: * Usage:
* var domElement = createDirective('myComponent', { * var domElement = createDirective(document, 'myComponent', {
* attrA: 'initial-value' * attrA: 'initial-value'
* }, { * }, {
* scopePropery: scopeValue * scopePropery: scopeValue
...@@ -25,7 +25,7 @@ function hyphenate(name) { ...@@ -25,7 +25,7 @@ function hyphenate(name) {
* *
* The initial value may be a callback function to invoke. eg: * The initial value may be a callback function to invoke. eg:
* *
* var domElement = createDirective('myComponent', { * var domElement = createDirective(document, 'myComponent', {
* onEvent: function () { * onEvent: function () {
* console.log('event triggered'); * console.log('event triggered');
* } * }
...@@ -34,7 +34,7 @@ function hyphenate(name) { ...@@ -34,7 +34,7 @@ function hyphenate(name) {
* If the callback accepts named arguments, these need to be specified * If the callback accepts named arguments, these need to be specified
* via an object with 'args' and 'callback' properties: * via an object with 'args' and 'callback' properties:
* *
* var domElement = createDirective('myComponent', { * var domElement = createDirective(document, 'myComponent', {
* onEvent: { * onEvent: {
* args: ['arg1'], * args: ['arg1'],
* callback: function (arg1) { * callback: function (arg1) {
......
...@@ -80,19 +80,6 @@ ThreadController = [ ...@@ -80,19 +80,6 @@ ThreadController = [
else else
return shouldShowUnfiltered return shouldShowUnfiltered
###*
# @ngdoc method
# @name thread.ThreadController#shouldShowNumReplies
# @description
# Returns a boolean indicating whether the reply count should be rendered
# for the annotation at the root of this thread.
###
this.shouldShowNumReplies = ->
hasChildren = this._count('message') > 0
allRepliesShown = this._count('message') == this._count('match')
hasFilterMatch = !this._isFilterActive() || allRepliesShown
hasChildren && hasFilterMatch
###* ###*
# @ngdoc method # @ngdoc method
# @name thread.ThreadController#numReplies # @name thread.ThreadController#numReplies
......
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
<span class="annotation-collapsed-replies"> <span class="annotation-collapsed-replies">
<a class="annotation-link" href="" <a class="annotation-link" href=""
ng-click="replyCountClick()" ng-click="vm.onReplyCountClick()"
ng-pluralize count="replyCount" ng-pluralize count="vm.replyCount"
when="{'0': '', 'one': '1 reply', 'other': '{} replies'}"></a> when="{'0': '', 'one': '1 reply', 'other': '{} replies'}"></a>
</span> </span>
...@@ -140,10 +140,10 @@ ...@@ -140,10 +140,10 @@
</a> </a>
</div> </div>
<div class="annotation-replies" ng-if="replyCount > 0"> <div class="annotation-replies" ng-if="vm.replyCount > 0">
<a class="annotation-link" href="" <a class="annotation-link" href=""
ng-click="replyCountClick()" ng-click="vm.onReplyCountClick()"
ng-pluralize count="replyCount" ng-pluralize count="vm.replyCount"
when="{'0': '', 'one': '1 reply', 'other': '{} replies'}"></a> when="{'0': '', 'one': '1 reply', 'other': '{} replies'}"></a>
</div> </div>
......
...@@ -11,17 +11,16 @@ ...@@ -11,17 +11,16 @@
<p><em>Message not available.</em></p> <p><em>Message not available.</em></p>
</div> </div>
<article class="annotation thread-message {{vm.collapsed && 'collapsed'}}" <annotation class="annotation thread-message {{vm.collapsed && 'collapsed'}}"
name="annotation" name="annotation"
annotation="vm.container.message" annotation="vm.container.message"
is-last-reply="$last" is-last-reply="$last"
is-sidebar="::isSidebar" is-sidebar="::isSidebar"
annotation-show-reply-count="{{vm.shouldShowNumReplies()}}" reply-count="vm.numReplies()"
annotation-reply-count="{{vm.numReplies()}}" on-reply-count-click="vm.toggleCollapsed()"
annotation-reply-count-click="vm.toggleCollapsed()"
ng-if="vm.container.message" ng-if="vm.container.message"
ng-show="vm.matchesFilter()"> ng-show="vm.matchesFilter()">
</article> </annotation>
<div class="thread-load-more" ng-show="vm.shouldShowLoadMore()"> <div class="thread-load-more" ng-show="vm.shouldShowLoadMore()">
<a class="load-more small" <a class="load-more small"
......
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