Commit 11abab35 authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #287 from hypothesis/use-ng-components

Convert element directives to components
parents dc979501 fff61fda
......@@ -135,38 +135,41 @@ module.exports = angular.module('h', [
// The root component for the application
.directive('hypothesisApp', require('./directive/app'))
// UI components and helpers
.directive('annotation', require('./directive/annotation').directive)
.directive('annotationShareDialog', require('./directive/annotation-share-dialog'))
.directive('annotationThread', require('./directive/annotation-thread'))
.directive('dropdownMenuBtn', require('./directive/dropdown-menu-btn'))
// UI components
.component('annotation', require('./directive/annotation').component)
.component('annotationShareDialog', require('./directive/annotation-share-dialog'))
.component('annotationThread', require('./directive/annotation-thread'))
.component('dropdownMenuBtn', require('./directive/dropdown-menu-btn'))
.component('helpLink', require('./directive/help-link'))
.component('helpPanel', require('./directive/help-panel'))
.component('loggedoutMessage', require('./directive/loggedout-message'))
.component('loginControl', require('./directive/login-control'))
.component('loginForm', require('./directive/login-form').component)
.component('publishAnnotationBtn', require('./directive/publish-annotation-btn'))
.component('searchInput', require('./directive/search-input'))
.component('searchStatusBar', require('./directive/search-status-bar'))
.component('selectionTabs', require('./directive/selection-tabs'))
.component('sidebarTutorial', require('./directive/sidebar-tutorial').component)
.component('shareDialog', require('./directive/share-dialog'))
.component('sortDropdown', require('./directive/sort-dropdown'))
.component('svgIcon', require('./directive/svg-icon'))
.component('tagEditor', require('./directive/tag-editor'))
.component('threadList', require('./directive/thread-list'))
.component('timestamp', require('./directive/timestamp'))
// These should use `component()` but will require some changes.
.directive('groupList', require('./directive/group-list').directive)
.directive('markdown', require('./directive/markdown'))
.directive('topBar', require('./directive/top-bar'))
.directive('excerpt', require('./directive/excerpt').directive)
.directive('formInput', require('./directive/form-input'))
.directive('formValidate', require('./directive/form-validate'))
.directive('groupList', require('./directive/group-list').directive)
.directive('helpLink', require('./directive/help-link'))
.directive('helpPanel', require('./directive/help-panel'))
.directive('hAutofocus', require('./directive/h-autofocus'))
.directive('hOnTouch', require('./directive/h-on-touch'))
.directive('hTooltip', require('./directive/h-tooltip'))
.directive('loggedoutMessage', require('./directive/loggedout-message'))
.directive('loginControl', require('./directive/login-control'))
.directive('loginForm', require('./directive/login-form').directive)
.directive('markdown', require('./directive/markdown'))
.directive('publishAnnotationBtn', require('./directive/publish-annotation-btn'))
.directive('searchStatusBar', require('./directive/search-status-bar'))
.directive('shareDialog', require('./directive/share-dialog'))
.directive('sidebarTutorial', require('./directive/sidebar-tutorial').directive)
.directive('searchInput', require('./directive/search-input'))
.directive('selectionTabs', require('./directive/selection-tabs'))
.directive('sortDropdown', require('./directive/sort-dropdown'))
.directive('spinner', require('./directive/spinner'))
.directive('statusButton', require('./directive/status-button'))
.directive('svgIcon', require('./directive/svg-icon'))
.directive('tagEditor', require('./directive/tag-editor'))
.directive('threadList', require('./directive/thread-list'))
.directive('timestamp', require('./directive/timestamp'))
.directive('topBar', require('./directive/top-bar'))
.directive('windowScroll', require('./directive/window-scroll'))
.service('analytics', require('./analytics'))
......
......@@ -4,11 +4,8 @@ var angular = require('angular');
var scopeTimeout = require('../util/scope-timeout');
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
restrict: 'E',
template: require('../templates/annotation_share_dialog.html'),
// @ngInject
controller: function ($scope, $element) {
......@@ -65,12 +62,11 @@ module.exports = function () {
}
}.bind(this);
},
scope: {
bindings: {
group: '<',
uri: '<',
isPrivate: '<',
isOpen: '<',
onClose: '&',
},
};
};
......@@ -97,13 +97,10 @@ function AnnotationThreadController() {
/**
* Renders a thread of annotations.
*/
module.exports = function () {
return {
restrict: 'E',
bindToController: true,
module.exports = {
controllerAs: 'vm',
controller: AnnotationThreadController,
scope: {
bindings: {
/** The annotation thread to render. */
thread: '<',
/**
......@@ -120,5 +117,4 @@ module.exports = function () {
onForceVisible: '&',
},
template: require('../templates/annotation_thread.html'),
};
};
......@@ -556,14 +556,10 @@ function AnnotationController(
init();
}
// @ngInject
function annotation() {
return {
restrict: 'E',
bindToController: true,
var component = {
controller: AnnotationController,
controllerAs: 'vm',
scope: {
bindings: {
annotation: '<',
showDocumentInfo: '<',
onReplyCountClick: '&',
......@@ -571,8 +567,7 @@ function annotation() {
isCollapsed: '<',
},
template: require('../templates/annotation.html'),
};
}
};
module.exports = {
// These private helper functions aren't meant to be part of the public
......@@ -583,6 +578,6 @@ module.exports = {
updateModel: updateModel,
// These are meant to be the public API of this module.
directive: annotation,
component: component,
Controller: AnnotationController,
};
'use strict';
// @ngInject
function DropdownMenuBtnController($scope, $timeout) {
this.onClick = function () {
$scope.onClick();
};
function DropdownMenuBtnController($timeout) {
var self = this;
this.toggleDropdown = function($event) {
$event.stopPropagation();
$timeout(function () {
$scope.onToggleDropdown();
self.onToggleDropdown();
}, 0);
};
}
module.exports = function () {
return {
module.exports = {
controller: DropdownMenuBtnController,
controllerAs: 'vm',
restrict: 'E',
scope: {
bindings: {
isDisabled: '<',
label: '<',
dropdownMenuLabel: '@',
......@@ -27,5 +22,4 @@ module.exports = function () {
onToggleDropdown: '&',
},
template: require('../templates/dropdown_menu_btn.html'),
};
};
'use strict';
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
restrict: 'E',
template: require('../templates/help_link.html'),
controller: function () {},
scope: {
......@@ -15,5 +12,4 @@ module.exports = function () {
auth: '<',
dateTime: '<',
},
};
};
......@@ -6,9 +6,7 @@
* @description Displays product version and environment info
*/
// @ngInject
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
// @ngInject
controller: function ($scope, $window, annotationUI, serviceUrl) {
......@@ -30,11 +28,9 @@ module.exports = function () {
}.bind(this)
);
},
restrict: 'E',
template: require('../templates/help_panel.html'),
scope: {
bindings: {
auth: '<',
onClose: '&',
},
};
};
'use strict';
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
//@ngInject
controller: function (serviceUrl) {
this.serviceUrl = serviceUrl;
},
restrict: 'E',
scope: {
bindings: {
/**
* Called when the user clicks on the "Log in" text.
*/
onLogin: '&',
},
template: require('../templates/loggedout_message.html'),
};
};
......@@ -2,9 +2,7 @@
var persona = require('../filter/persona');
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
//@ngInject
controller: function (serviceUrl, settings) {
......@@ -13,8 +11,7 @@ module.exports = function () {
return persona.isThirdPartyUser(this.auth.userid, settings.authDomain);
};
},
restrict: 'E',
scope: {
bindings: {
/**
* An object representing the current authentication status.
*/
......@@ -39,5 +36,4 @@ module.exports = function () {
newStyle: '<',
},
template: require('../templates/login_control.html'),
};
};
......@@ -93,18 +93,16 @@ function Controller($scope, $timeout, flash, session, formRespond, serviceUrl) {
});
}
module.exports = {
directive: function () {
return {
bindToController: true,
var component = {
controller: Controller,
controllerAs: 'vm',
restrict: 'E',
scope: {
bindings: {
onClose: '&',
},
template: require('../templates/login_form.html'),
};
},
};
module.exports = {
component: component,
Controller: Controller,
};
'use strict';
/**
* @ngdoc directive
* @name publishAnnotationBtn
* @description Displays a combined privacy/selection post button to post
* a new annotation
*/
// @ngInject
module.exports = function () {
return {
bindToController: true,
module.exports = {
controller: function () {
this.showDropdown = false;
this.privateLabel = 'Only Me';
......@@ -27,8 +23,7 @@ module.exports = function () {
};
},
controllerAs: 'vm',
restrict: 'E',
scope: {
bindings: {
group: '<',
canPost: '<',
isShared: '<',
......@@ -37,5 +32,4 @@ module.exports = function () {
onSetPrivacy: '&',
},
template: require('../templates/publish_annotation_btn.html'),
};
};
......@@ -32,14 +32,10 @@ function SearchInputController($element, $http, $scope) {
};
}
// @ngInject
module.exports = function () {
return {
bindToController: true,
module.exports = {
controller: SearchInputController,
controllerAs: 'vm',
restrict: 'E',
scope: {
bindings: {
// Specifies whether the search input field should always be expanded,
// regardless of whether the it is focused or has an active query.
//
......@@ -49,5 +45,4 @@ module.exports = function () {
onSearch: '&',
},
template: require('../templates/search_input.html'),
};
};
......@@ -2,18 +2,14 @@
var uiConstants = require('../ui-constants');
// @ngInject
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
controller: function () {
this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS;
this.TAB_NOTES = uiConstants.TAB_NOTES;
this.TAB_ORPHANS = uiConstants.TAB_ORPHANS;
},
restrict: 'E',
scope: {
bindings: {
filterActive: '<',
filterMatchCount: '<',
onClearSelection: '&',
......@@ -24,5 +20,4 @@ module.exports = function () {
totalNotes: '<',
},
template: require('../templates/search_status_bar.html'),
};
};
......@@ -2,9 +2,7 @@
var uiConstants = require('../ui-constants');
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
//@ngInject
controller: function ($element, annotationUI, features) {
......@@ -32,8 +30,7 @@ module.exports = function () {
this.totalNotes === 0;
};
},
restrict: 'E',
scope: {
bindings: {
isLoading: '<',
isWaitingToAnchorAnnotations: '<',
selectedTab: '<',
......@@ -42,5 +39,4 @@ module.exports = function () {
totalOrphans: '<',
},
template: require('../templates/selection_tabs.html'),
};
};
......@@ -28,15 +28,11 @@ function ShareDialogController($scope, $element, annotationUI) {
updateViaLink);
}
module.exports = function () {
return {
restrict: 'E',
bindToController: true,
module.exports = {
controller: ShareDialogController,
controllerAs: 'vm',
scope: {
bindings: {
onClose: '&',
},
template: require('../templates/share_dialog.html'),
};
};
......@@ -17,21 +17,16 @@ function SidebarTutorialController(session) {
}
/**
* @ngdoc directive
* @name sidebarTutorial
* @description Displays a short tutorial in the sidebar.
*/
// @ngInject
module.exports = {
directive: function () {
return {
bindToController: true,
component: {
controller: SidebarTutorialController,
controllerAs: 'vm',
restrict: 'E',
scope: {},
bindings: {},
template: require('../templates/sidebar_tutorial.html'),
};
},
Controller: SidebarTutorialController,
};
'use strict';
module.exports = function () {
return {
module.exports = {
controllerAs: 'vm',
controller: function () {},
restrict: 'E',
scope: {
bindings: {
/** The name of the currently selected sort key. */
sortKey: '<',
/** A list of possible keys that the user can opt to sort by. */
......@@ -13,5 +12,4 @@ module.exports = function () {
onChangeSortKey: '&',
},
template: require('../templates/sort_dropdown.html'),
};
};
......@@ -21,15 +21,11 @@ function SvgIconController($element) {
$element[0].innerHTML = icons[this.name];
}
module.exports = function () {
return {
bindToController: true,
module.exports = {
controllerAs: 'vm',
restrict: 'E',
controller: SvgIconController,
scope: {
bindings: {
/** The name of the icon to load. */
name: '<',
},
};
};
......@@ -22,16 +22,12 @@ function TagEditorController(tags) {
};
}
module.exports = function () {
return {
bindToController: true,
module.exports = {
controller: TagEditorController,
controllerAs: 'vm',
restrict: 'E',
scope: {
bindings: {
tags: '<',
onEditTags: '&',
},
template: require('../templates/tag_editor.html'),
};
};
......@@ -13,7 +13,7 @@ describe('annotationShareDialog', function () {
before(function () {
angular.module('app', [])
.directive('annotationShareDialog',
.component('annotationShareDialog',
require('../annotation-share-dialog'))
.value('urlEncodeFilter', function (val) { return val; });
});
......
......@@ -20,7 +20,7 @@ var fakeDocumentMeta = {
/**
* Returns the annotation directive with helpers stubbed out.
*/
function annotationDirective() {
function annotationComponent() {
var noop = function () { return ''; };
var annotation = proxyquire('../annotation', {
......@@ -35,7 +35,7 @@ function annotationDirective() {
},
});
return annotation.directive;
return annotation.component;
}
describe('annotation', function() {
......@@ -116,7 +116,7 @@ describe('annotation', function() {
before(function() {
angular.module('h', [])
.directive('annotation', annotationDirective());
.component('annotation', annotationComponent());
});
beforeEach(angular.mock.module('h'));
......
......@@ -25,7 +25,7 @@ function PageObject(element) {
describe('annotationThread', function () {
before(function () {
angular.module('app', [])
.directive('annotationThread', annotationThread);
.component('annotationThread', annotationThread);
});
beforeEach(function () {
......
......@@ -28,7 +28,7 @@ function PageObject(element) {
describe('loginControl', function () {
before(function () {
angular.module('app', [])
.directive('loginControl', require('../login-control'));
.component('loginControl', require('../login-control'));
});
beforeEach(function () {
......
......@@ -17,8 +17,8 @@ var fakeLocalStorage = {
describe('publishAnnotationBtn', function () {
before(function () {
angular.module('app', [])
.directive('dropdownMenuBtn', require('../dropdown-menu-btn'))
.directive('publishAnnotationBtn', require('../publish-annotation-btn'))
.component('dropdownMenuBtn', require('../dropdown-menu-btn'))
.component('publishAnnotationBtn', require('../publish-annotation-btn'))
.factory('localStorage', function () {
return fakeLocalStorage;
});
......
......@@ -9,7 +9,7 @@ describe('searchInput', function () {
before(function () {
angular.module('app', [])
.directive('searchInput', require('../search-input'));
.component('searchInput', require('../search-input'));
});
beforeEach(function () {
......
......@@ -7,7 +7,7 @@ var util = require('./util');
describe('searchStatusBar', function () {
before(function () {
angular.module('app', [])
.directive('searchStatusBar', require('../search-status-bar'));
.component('searchStatusBar', require('../search-status-bar'));
});
beforeEach(function () {
......
......@@ -7,7 +7,7 @@ var util = require('./util');
describe('selectionTabs', function () {
before(function () {
angular.module('app', [])
.directive('selectionTabs', require('../selection-tabs'));
.component('selectionTabs', require('../selection-tabs'));
});
beforeEach(function () {
......
......@@ -11,7 +11,7 @@ describe('shareDialog', function () {
fakeAnnotationUI = { frames: sinon.stub().returns([]) };
angular.module('h', [])
.directive('shareDialog', require('../share-dialog'))
.component('shareDialog', require('../share-dialog'))
.value('annotationUI', fakeAnnotationUI)
.value('urlEncodeFilter', function (val) { return val; });
angular.mock.module('h');
......
......@@ -7,7 +7,7 @@ var util = require('./util');
describe('sortDropdown', function () {
before(function () {
angular.module('app', [])
.directive('sortDropdown', require('../sort-dropdown'));
.component('sortDropdown', require('../sort-dropdown'));
});
beforeEach(function () {
......
......@@ -7,7 +7,7 @@ var util = require('./util');
describe('svgIcon', function () {
before(function () {
angular.module('app', [])
.directive('svgIcon', require('../svg-icon'));
.component('svgIcon', require('../svg-icon'));
});
beforeEach(function () {
......
......@@ -9,7 +9,7 @@ describe('tagEditor', function () {
before(function () {
angular.module('app',[])
.directive('tagEditor', require('../tag-editor'));
.component('tagEditor', require('../tag-editor'));
});
beforeEach(function () {
......
......@@ -84,7 +84,7 @@ describe('threadList', function () {
before(function () {
angular.module('app', [])
.directive('threadList', threadList);
.component('threadList', threadList);
});
beforeEach(function () {
......
......@@ -11,7 +11,7 @@ describe('timestamp', function () {
before(function () {
angular.module('app',[])
.directive('timestamp', require('../timestamp'));
.component('timestamp', require('../timestamp'));
});
beforeEach(function () {
......
......@@ -126,13 +126,10 @@ function ThreadListController($scope, VirtualThreadList) {
};
}
module.exports = function () {
return {
bindToController: true,
module.exports = {
controller: ThreadListController,
controllerAs: 'vm',
restrict: 'E',
scope: {
bindings: {
/** The root thread to be displayed by the thread list. */
thread: '<',
showDocumentInfo: '<',
......@@ -152,5 +149,4 @@ module.exports = function () {
onClearSelection: '&',
},
template: require('../templates/thread_list.html'),
};
};
......@@ -42,13 +42,10 @@ function TimestampController($scope, time) {
};
}
module.exports = function () {
return {
bindToController: true,
module.exports = {
controller: TimestampController,
controllerAs: 'vm',
restrict: 'E',
scope: {
bindings: {
className: '<',
href: '<',
timestamp: '<',
......@@ -56,5 +53,4 @@ module.exports = function () {
template: ['<a class="{{vm.className}}" target="_blank" ng-title="vm.absoluteTimestamp"',
' href="{{vm.href}}"',
'>{{vm.relativeTimestamp}}</a>'].join(''),
};
};
<div class="dropdown-menu-btn">
<button
class="dropdown-menu-btn__btn"
ng-bind="label"
ng-bind="vm.label"
ng-click="vm.onClick($event)"
ng-disabled="isDisabled">
ng-disabled="vm.isDisabled">
</button>
<button
class="dropdown-menu-btn__dropdown-arrow"
title="{{dropdownMenuLabel}}"
title="{{vm.dropdownMenuLabel}}"
ng-click="vm.toggleDropdown($event)">
<div class="dropdown-menu-btn__dropdown-arrow-separator"></div>
<div class="dropdown-menu-btn__dropdown-arrow-indicator">
......
......@@ -3,16 +3,16 @@
type="button"
class="top-bar__btn"
dropdown-toggle
title="Sort by {{sortKey}}">
title="Sort by {{vm.sortKey}}">
<i class="h-icon-sort"></i>
</button>
<div class="dropdown-menu__top-arrow"></div>
<ul class="dropdown-menu pull-right" role="menu">
<li class="dropdown-menu__row"
ng-repeat="key in sortKeysAvailable"
ng-click="onChangeSortKey({sortKey: key})"
ng-repeat="key in vm.sortKeysAvailable"
ng-click="vm.onChangeSortKey({sortKey: key})"
><span class="dropdown-menu-radio"
ng-class="{'is-selected' : sortKey === key}"
ng-class="{'is-selected' : vm.sortKey === key}"
></span><a class="dropdown-menu__link" href="">{{key}}</a></li>
</ul>
</span>
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