Unverified Commit b7a83942 authored by Robert Knight's avatar Robert Knight Committed by GitHub

Merge pull request #718 from hypothesis/logos-in-groups-menu

Add organization logos to groups menu
parents 24c70160 f775e0d3
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
var { isThirdPartyUser } = require('../util/account-id'); var { isThirdPartyUser } = require('../util/account-id');
var isThirdPartyService = require('../util/is-third-party-service'); var isThirdPartyService = require('../util/is-third-party-service');
var serviceConfig = require('../service-config'); var serviceConfig = require('../service-config');
const memoize = require('../util/memoize');
const groupOrganizations = memoize(require('../util/group-organizations'));
// @ngInject // @ngInject
function GroupListController($window, analytics, groups, settings, serviceUrl) { function GroupListController($window, analytics, groups, settings, serviceUrl) {
...@@ -12,6 +14,18 @@ function GroupListController($window, analytics, groups, settings, serviceUrl) { ...@@ -12,6 +14,18 @@ function GroupListController($window, analytics, groups, settings, serviceUrl) {
$window.open(serviceUrl('groups.new'), '_blank'); $window.open(serviceUrl('groups.new'), '_blank');
}; };
this.focusedIcon = function() {
const focusedGroup = this.groups.focused();
return focusedGroup && (
focusedGroup.organization.logo || this.thirdPartyGroupIcon
);
};
this.focusedIconClass = function() {
const focusedGroup = this.groups.focused();
return (focusedGroup && focusedGroup.type === 'private') ? 'group' : 'public';
};
this.isThirdPartyUser = function () { this.isThirdPartyUser = function () {
return isThirdPartyUser(this.auth.userid, settings.authDomain); return isThirdPartyUser(this.auth.userid, settings.authDomain);
}; };
...@@ -26,6 +40,15 @@ function GroupListController($window, analytics, groups, settings, serviceUrl) { ...@@ -26,6 +40,15 @@ function GroupListController($window, analytics, groups, settings, serviceUrl) {
} }
}; };
this.orgName = function (groupId) {
const group = this.groups.get(groupId);
return group && group.organization && group.organization.name;
};
this.groupOrganizations = function () {
return groupOrganizations(this.groups.all());
};
this.viewGroupActivity = function () { this.viewGroupActivity = function () {
analytics.track(analytics.events.GROUP_VIEW_ACTIVITY); analytics.track(analytics.events.GROUP_VIEW_ACTIVITY);
}; };
......
...@@ -5,6 +5,8 @@ var angular = require('angular'); ...@@ -5,6 +5,8 @@ var angular = require('angular');
var groupList = require('../group-list'); var groupList = require('../group-list');
var util = require('../../directive/test/util'); var util = require('../../directive/test/util');
var groupFixtures = require('../../test/group-fixtures');
describe('groupList', function () { describe('groupList', function () {
var $window; var $window;
...@@ -58,6 +60,7 @@ describe('groupList', function () { ...@@ -58,6 +60,7 @@ describe('groupList', function () {
html: OPEN_GROUP_LINK, html: OPEN_GROUP_LINK,
}, },
name: 'Public Group', name: 'Public Group',
organization: groupFixtures.defaultOrganization(),
type: 'open', type: 'open',
},{ },{
id: 'h-devs', id: 'h-devs',
...@@ -65,6 +68,7 @@ describe('groupList', function () { ...@@ -65,6 +68,7 @@ describe('groupList', function () {
html: PRIVATE_GROUP_LINK, html: PRIVATE_GROUP_LINK,
}, },
name: 'Hypothesis Developers', name: 'Hypothesis Developers',
organization: groupFixtures.defaultOrganization(),
type: 'private', type: 'private',
}, { }, {
id: 'restricto', id: 'restricto',
...@@ -72,6 +76,7 @@ describe('groupList', function () { ...@@ -72,6 +76,7 @@ describe('groupList', function () {
html: RESTRICTED_GROUP_LINK, html: RESTRICTED_GROUP_LINK,
}, },
name: 'Hello Restricted', name: 'Hello Restricted',
organization: groupFixtures.defaultOrganization(),
type: 'restricted', type: 'restricted',
}]; }];
...@@ -116,6 +121,101 @@ describe('groupList', function () { ...@@ -116,6 +121,101 @@ describe('groupList', function () {
assert.include(nameLinks[2].title, 'Show public annotations'); // Restricted assert.include(nameLinks[2].title, 'Show public annotations'); // Restricted
}); });
it('should render organization logo for focused group', function () {
const org = groupFixtures.organization({ logo: 'http://www.example.com/foobar' });
const group = groupFixtures.expandedGroup({
organization: org,
});
fakeGroups.focused = () => { return group; };
const element = createGroupList();
const imgEl = element.find('.dropdown-toggle > img.group-list-label__icon');
assert.equal(imgEl[0].src, org.logo);
});
it('should render fallback icon for focused group when no logo (private)', function () {
const org = groupFixtures.organization({ logo: null });
const group = groupFixtures.expandedGroup({
organization: org,
type: 'private',
});
fakeGroups.focused = () => { return group; };
const element = createGroupList();
const iconEl = element.find('.dropdown-toggle > i.h-icon-group');
assert.ok(iconEl[0]);
});
it('should render fallback icon for focused group when no logo (restricted)', function () {
const org = groupFixtures.organization({ logo: null });
const group = groupFixtures.expandedGroup({
organization: org,
type: 'restricted',
});
fakeGroups.focused = () => { return group; };
const element = createGroupList();
const iconEl = element.find('.dropdown-toggle > i.h-icon-public');
assert.ok(iconEl[0]);
});
it('should render fallback icon for focused group when no logo (open)', function () {
const org = groupFixtures.organization({ logo: null });
const group = groupFixtures.expandedGroup({
organization: org,
type: 'open',
});
fakeGroups.focused = () => { return group; };
const element = createGroupList();
const iconEl = element.find('.dropdown-toggle > i.h-icon-public');
assert.ok(iconEl[0]);
});
it('should render organization icons for first group in each organization', function () {
const orgs = [
groupFixtures.defaultOrganization(),
groupFixtures.organization(),
];
groups = [
groupFixtures.expandedGroup({ organization: orgs[0] }),
groupFixtures.expandedGroup({ organization: orgs[0] }),
groupFixtures.expandedGroup({ organization: orgs[1] }),
groupFixtures.expandedGroup({ organization: orgs[1] }),
];
const element = createGroupList();
const iconContainers = element.find('.group-menu-icon-container');
const iconImages = element.find('.group-menu-icon-container > img');
assert.lengthOf(iconContainers, groups.length);
assert.lengthOf(iconImages, orgs.length);
});
it('should not render organization icons for menu groups if missing', function () {
const orgs = [
groupFixtures.organization({ logo: null }),
groupFixtures.organization({ logo: null }),
];
groups = [
groupFixtures.expandedGroup({ organization: orgs[0] }),
groupFixtures.expandedGroup({ organization: orgs[0] }),
groupFixtures.expandedGroup({ organization: orgs[1] }),
groupFixtures.expandedGroup({ organization: orgs[1] }),
];
const element = createGroupList();
const iconContainers = element.find('.group-menu-icon-container');
const iconImages = element.find('.group-menu-icon-container > img');
assert.lengthOf(iconContainers, groups.length);
assert.lengthOf(iconImages, 0);
});
it('should render share links', function () { it('should render share links', function () {
var element = createGroupList(); var element = createGroupList();
var shareLinks = element.find('.share-link-container'); var shareLinks = element.find('.share-link-container');
......
...@@ -5,34 +5,28 @@ ...@@ -5,34 +5,28 @@
dropdown-toggle dropdown-toggle
data-toggle="dropdown" data-toggle="dropdown"
role="button" role="button"
ng-switch on="vm.groups.focused().type == 'open'"
title="Change the selected group"> title="Change the selected group">
<img class="group-list-label__icon group-list-label__icon--third-party" <img class="group-list-label__icon group-list-label__icon--organization"
ng-src="{{ vm.thirdPartyGroupIcon }}" ng-src="{{ vm.focusedIcon() }}"
ng-if="vm.thirdPartyGroupIcon" alt="{{ vm.orgName(vm.groups.focused().id)}}"
ng-switch-when="true"><!-- nospace ng-if="vm.focusedIcon()">
!--><i class="group-list-label__icon h-icon-public" <i class="group-list-label__icon h-icon-{{ vm.focusedIconClass() }}"
ng-switch-when="true" ng-if="!vm.focusedIcon()"></i><!-- nospace
ng-if="!vm.thirdPartyGroupIcon"></i><!-- nospace !--><span class="group-list-label__label">{{vm.groups.focused().name}}</span><!-- nospace
!--><i class="group-list-label__icon h-icon-group" !--><i class="h-icon-arrow-drop-down"></i>
ng-switch-default></i>
<span class="group-list-label__label">{{vm.groups.focused().name}}</span><!-- nospace
!--><i class="h-icon-arrow-drop-down"></i>
</div> </div>
<div class="dropdown-menu__top-arrow"></div> <div class="dropdown-menu__top-arrow"></div>
<ul class="dropdown-menu pull-none" role="menu"> <ul class="dropdown-menu pull-none" role="menu">
<li class="dropdown-menu__row dropdown-menu__row--unpadded " <li class="dropdown-menu__row dropdown-menu__row--unpadded "
ng-repeat="group in vm.groups.all()"> ng-repeat="group in vm.groupOrganizations() track by group.id">
<div ng-class="{'group-item': true, selected: group.id == vm.groups.focused().id}" <div ng-class="{'group-item': true, selected: group.id == vm.groups.focused().id}"
ng-click="vm.focusGroup(group.id)"> ng-click="vm.focusGroup(group.id)">
<!-- the group icon !--> <!-- the group icon !-->
<div class="group-icon-container" ng-switch on="group.type == 'open'"> <div class="group-menu-icon-container">
<img class="group-list-label__icon group-list-label__icon--third-party" <img class="group-list-label__icon group-list-label__icon--organization"
ng-src="{{ vm.thirdPartyGroupIcon }}" alt="{{ vm.orgName(group.id) }}"
ng-if="vm.thirdPartyGroupIcon" ng-src="{{ group.logo }}"
ng-switch-when="true"> ng-if="group.logo">
<i class="h-icon-public" ng-if="!vm.thirdPartyGroupIcon" ng-switch-when="true"></i>
<i class="h-icon-group" ng-switch-default></i>
</div> </div>
<!-- the group name and share link !--> <!-- the group name and share link !-->
<div class="group-details"> <div class="group-details">
...@@ -69,7 +63,7 @@ ...@@ -69,7 +63,7 @@
<div class="group-icon-container"><i class="h-icon-add"></i></div> <div class="group-icon-container"><i class="h-icon-add"></i></div>
<div class="group-details"> <div class="group-details">
<a href="" class="group-name-link" title="Create a new group to share annotations"> <a href="" class="group-name-link" title="Create a new group to share annotations">
New group New private group
</a> </a>
</div> </div>
</div> </div>
......
...@@ -47,6 +47,12 @@ $group-list-spacing-below: 50px; ...@@ -47,6 +47,12 @@ $group-list-spacing-below: 50px;
margin-right: 10px; margin-right: 10px;
} }
.group-menu-icon-container {
margin-right: 10px;
width: 15px;
height: 15px;
}
.group-cancel-icon-container { .group-cancel-icon-container {
// the 'Leave group' icon is shifted down slightly // the 'Leave group' icon is shifted down slightly
// so that it lines up vertically with the 'chat heads' icon on the // so that it lines up vertically with the 'chat heads' icon on the
...@@ -88,7 +94,7 @@ $group-list-spacing-below: 50px; ...@@ -88,7 +94,7 @@ $group-list-spacing-below: 50px;
transform: translateY(1px); transform: translateY(1px);
} }
.group-list-label__icon--third-party { .group-list-label__icon--organization {
height: 15px; height: 15px;
width: 15px; width: 15px;
top: 2px; top: 2px;
......
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