diff --git a/src/sidebar/app.js b/src/sidebar/app.js index 870a790bc86..23bf66ed1a6 100644 --- a/src/sidebar/app.js +++ b/src/sidebar/app.js @@ -170,6 +170,7 @@ module.exports = angular.module('h', [ .component('threadList', require('./components/thread-list')) .component('timestamp', require('./components/timestamp')) .component('topBar', require('./components/top-bar')) + .component('viewSwitcher', require('./components/view-switcher')) .directive('formInput', require('./directive/form-input')) .directive('formValidate', require('./directive/form-validate')) diff --git a/src/sidebar/components/sidebar-content.js b/src/sidebar/components/sidebar-content.js index 2275795aaca..4eb48ae5817 100644 --- a/src/sidebar/components/sidebar-content.js +++ b/src/sidebar/components/sidebar-content.js @@ -55,6 +55,7 @@ function SidebarContentController( totalNotes: counts.notes, totalAnnotations: counts.annotations, totalOrphans: counts.orphans, + viewSwitcherEnabled: features.flagEnabled('view-switcher'), waitingToAnchorAnnotations: counts.anchoring > 0, }); }); diff --git a/src/sidebar/components/test/view-switcher-test.js b/src/sidebar/components/test/view-switcher-test.js new file mode 100644 index 00000000000..59b487db35b --- /dev/null +++ b/src/sidebar/components/test/view-switcher-test.js @@ -0,0 +1,63 @@ +'use strict'; + +var angular = require('angular'); + +var util = require('../../directive/test/util'); + +describe('viewSwitcher', function () { + before(function () { + angular.module('app', []) + .component('viewSwitcher', require('../view-switcher')); + }); + + beforeEach(function () { + var fakeAnnotationUI = {}; + var fakeFeatures = { + flagEnabled: sinon.stub().returns(true), + }; + + angular.mock.module('app', { + annotationUI: fakeAnnotationUI, + features: fakeFeatures, + }); + }); + + context('displays tabs, counts and selected tab', function () { + it('should display the tabs and counts of annotations and notes', function () { + var elem = util.createDirective(document, 'viewSwitcher', { + selectedTab: 'annotation', + totalAnnotations: '123', + totalNotes: '456', + }); + + var tabs = elem[0].querySelectorAll('button'); + + assert.include(tabs[0].textContent, 'Annotations'); + assert.include(tabs[1].textContent, 'Notes'); + assert.include(tabs[0].textContent, '123'); + assert.include(tabs[1].textContent, '456'); + }); + + it('should display annotations tab as selected', function () { + var elem = util.createDirective(document, 'viewSwitcher', { + selectedTab: 'annotation', + totalAnnotations: '123', + totalNotes: '456', + }); + + var tabs = elem[0].querySelectorAll('button'); + assert.isTrue(tabs[0].classList.contains('is-selected')); + }); + + it('should display notes tab as selected', function () { + var elem = util.createDirective(document, 'viewSwitcher', { + selectedTab: 'note', + totalAnnotations: '123', + totalNotes: '456', + }); + + var tabs = elem[0].querySelectorAll('button'); + assert.isTrue(tabs[1].classList.contains('is-selected')); + }); + }); +}); diff --git a/src/sidebar/components/view-switcher.js b/src/sidebar/components/view-switcher.js new file mode 100644 index 00000000000..24da331aed6 --- /dev/null +++ b/src/sidebar/components/view-switcher.js @@ -0,0 +1,42 @@ +'use strict'; + +var uiConstants = require('../ui-constants'); + +module.exports = { + controllerAs: 'vm', + //@ngInject + controller: function ($element, annotationUI, features) { + this.TAB_ANNOTATIONS = uiConstants.TAB_ANNOTATIONS; + this.TAB_NOTES = uiConstants.TAB_NOTES; + this.TAB_ORPHANS = uiConstants.TAB_ORPHANS; + + this.selectTab = function (type) { + annotationUI.clearSelectedAnnotations(); + annotationUI.selectTab(type); + }; + + this.orphansTabFlagEnabled = function () { + return features.flagEnabled('orphans_tab'); + }; + + this.showAnnotationsUnavailableMessage = function () { + return this.selectedTab === this.TAB_ANNOTATIONS && + this.totalAnnotations === 0 && + !this.isWaitingToAnchorAnnotations; + }; + + this.showNotesUnavailableMessage = function () { + return this.selectedTab === this.TAB_NOTES && + this.totalNotes === 0; + }; + }, + bindings: { + isLoading: '<', + isWaitingToAnchorAnnotations: '<', + selectedTab: '<', + totalAnnotations: '<', + totalNotes: '<', + totalOrphans: '<', + }, + template: require('../templates/view-switcher.html'), +}; diff --git a/src/sidebar/templates/sidebar-content.html b/src/sidebar/templates/sidebar-content.html index e5da39e1c62..bebcf658486 100644 --- a/src/sidebar/templates/sidebar-content.html +++ b/src/sidebar/templates/sidebar-content.html @@ -1,5 +1,5 @@ + + + + + Annotations + + + {{ vm.totalAnnotations }} + + + + + + Page Notes + + + {{ vm.totalNotes }} + + + + + + Orphans + + + {{ vm.totalOrphans }} + + + + + + + + There are no page notes in this group. + + Create one by clicking the + + button. + + + + + There are no annotations in this group. + + Create one by selecting some text and clicking the + button. + + + diff --git a/src/styles/app.scss b/src/styles/app.scss index 881d2432d57..75313e9903b 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -31,6 +31,7 @@ $base-line-height: 20px; @import './thread-list'; @import './tooltip'; @import './top-bar'; +@import './view-switcher'; // Top-level styles // ---------------- diff --git a/src/styles/view-switcher.scss b/src/styles/view-switcher.scss new file mode 100644 index 00000000000..36b7ab8af0f --- /dev/null +++ b/src/styles/view-switcher.scss @@ -0,0 +1,61 @@ +.view-switcher { + display: flex; + justify-content: center; + + // These are the exact margins required to vertically align the top of the + // view switcher with the top of the Hide Highlights button to its left, + // and the top of the first annotation card below the view switcher with the + // top of the New Page Note button to its left. + margin-top: 1px; + margin-bottom: 6px; +} + +.view-switcher__tab { + @include smallshadow + + height: 30px; // Same height as used for Hide Highlights and New Page Note + // buttons to left of view switcher. + padding-left: 12px; + padding-right: 12px; + + background: $white; + transition: background-color .1s linear; + + border: 1px solid $gray-lighter; + + cursor: pointer; + user-select: none; +} + +.view-switcher__tab { + border-right-width: 0; +} +.view-switcher__tab:last-child { + border-right-width: 1px; +} + +.view-switcher__tab:first-child { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.view-switcher__tab:last-child { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.view-switcher__tab:focus { + outline: 0; +} +.view-switcher__tab::-moz-focus-inner { + border: 0; +} + +.view-switcher__tab:hover, +.view-switcher__tab.is-selected { + background-color: #e6e6e6; +} + +.view-switcher__empty-message { + position: relative; + top: 10px; +}
+ There are no page notes in this group. + + Create one by clicking the + + button. +
+ There are no annotations in this group. + + Create one by selecting some text and clicking the + button. +