From b535be35ae8bbb003f550e51d22a8e3b4c46b07c Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Mon, 31 Jul 2017 16:03:39 +0530 Subject: Group Identicon for groups without avatars --- .../groups/components/group_identicon.vue | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 app/assets/javascripts/groups/components/group_identicon.vue diff --git a/app/assets/javascripts/groups/components/group_identicon.vue b/app/assets/javascripts/groups/components/group_identicon.vue new file mode 100644 index 00000000000..4e0898b6c44 --- /dev/null +++ b/app/assets/javascripts/groups/components/group_identicon.vue @@ -0,0 +1,44 @@ + + + -- cgit v1.2.1 From 84568997431d778644d41dd3e3a4f98eee850935 Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Mon, 31 Jul 2017 16:04:25 +0530 Subject: Use GroupIdenticon for missing avatars --- app/assets/javascripts/groups/components/group_item.vue | 13 +++++++++++++ app/assets/javascripts/groups/index.js | 2 ++ 2 files changed, 15 insertions(+) diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue index b1db34b9c50..c704aa65df2 100644 --- a/app/assets/javascripts/groups/components/group_item.vue +++ b/app/assets/javascripts/groups/components/group_item.vue @@ -92,6 +92,13 @@ export default { hasGroups() { return Object.keys(this.group.subGroups).length > 0; }, + hasAvatar() { + if (this.group.avatarUrl) { + return this.group.avatarUrl.indexOf('/assets/no_group_avatar') === -1; + } else { + return false; + } + }, }, }; @@ -194,9 +201,15 @@ export default { +
{ Vue.component('groups-component', GroupsComponent); Vue.component('group-folder', GroupFolder); Vue.component('group-item', GroupItem); + Vue.component('group-identicon', GroupIdenticon); // eslint-disable-next-line no-new new Vue({ -- cgit v1.2.1 From ec0ea51f67724be9ae2a81827abeec9022cd2f46 Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Mon, 31 Jul 2017 16:04:45 +0530 Subject: Add styles for Identicons for Groups --- app/assets/stylesheets/framework/lists.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 868e65a8f46..ab754f4a492 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -369,6 +369,10 @@ ul.indent-list { background-color: $row-hover; cursor: pointer; } + + .avatar-container > a { + width: 100%; + } } } -- cgit v1.2.1 From 339469099d64e9f87cccb375cc31c0158a99480f Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Mon, 31 Jul 2017 16:05:06 +0530 Subject: Update tests --- spec/javascripts/groups/groups_spec.js | 15 +++++++++++++++ spec/javascripts/groups/mock_data.js | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/spec/javascripts/groups/groups_spec.js b/spec/javascripts/groups/groups_spec.js index aaffb56fa94..7e38b49c792 100644 --- a/spec/javascripts/groups/groups_spec.js +++ b/spec/javascripts/groups/groups_spec.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import eventHub from '~/groups/event_hub'; import groupFolderComponent from '~/groups/components/group_folder.vue'; import groupItemComponent from '~/groups/components/group_item.vue'; +import groupIdenticonComponent from '~/groups/components/group_identicon.vue'; import groupsComponent from '~/groups/components/groups.vue'; import GroupsStore from '~/groups/stores/groups_store'; import { groupsData } from './mock_data'; @@ -14,6 +15,7 @@ describe('Groups Component', () => { beforeEach((done) => { Vue.component('group-folder', groupFolderComponent); + Vue.component('group-identicon', groupIdenticonComponent); Vue.component('group-item', groupItemComponent); store = new GroupsStore(); @@ -64,6 +66,19 @@ describe('Groups Component', () => { expect(lists[2].querySelector('#group-1120').textContent).toContain(groups.id1119.subGroups.id1120.name); }); + it('should render group identicon when group avatar is not present', () => { + const avatar = component.$el.querySelector('#group-12 .avatar-container .avatar'); + expect(avatar.nodeName).toBe('DIV'); + expect(avatar.classList.contains('identicon')).toBeTruthy(); + expect(avatar.getAttribute('style').indexOf('background-color') > -1).toBeTruthy(); + }); + + it('should render group avatar when group avatar is present', () => { + const avatar = component.$el.querySelector('#group-1120 .avatar-container .avatar'); + expect(avatar.nodeName).toBe('IMG'); + expect(avatar.classList.contains('identicon')).toBeFalsy(); + }); + it('should remove prefix of parent group', () => { expect(component.$el.querySelector('#group-12 #group-1128 .title').textContent).toContain('level2 / level3 / level4'); }); diff --git a/spec/javascripts/groups/mock_data.js b/spec/javascripts/groups/mock_data.js index b3f5d791b89..9e1f414514a 100644 --- a/spec/javascripts/groups/mock_data.js +++ b/spec/javascripts/groups/mock_data.js @@ -71,7 +71,7 @@ const group21 = { path: 'chef', description: 'foo', visibility: 'public', - avatar_url: null, + avatar_url: '/uploads/-/system/group/avatar/2/GitLab.png', web_url: 'http://localhost:3000/groups/devops/chef', group_path: '/devops/chef', full_name: 'devops / chef', -- cgit v1.2.1 From d03ea6d40a923f233c71000808e333809791bc26 Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Tue, 1 Aug 2017 14:36:17 +0530 Subject: Change ID type to number --- spec/javascripts/groups/mock_data.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/javascripts/groups/mock_data.js b/spec/javascripts/groups/mock_data.js index 9e1f414514a..5bb84b591f4 100644 --- a/spec/javascripts/groups/mock_data.js +++ b/spec/javascripts/groups/mock_data.js @@ -1,5 +1,5 @@ const group1 = { - id: '12', + id: 12, name: 'level1', path: 'level1', description: 'foo', -- cgit v1.2.1 From 53fb22bcc3458598de9cebd60ae64a5f96937d5e Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Tue, 1 Aug 2017 14:36:30 +0530 Subject: Remove unnecessary imports --- spec/javascripts/groups/groups_spec.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/javascripts/groups/groups_spec.js b/spec/javascripts/groups/groups_spec.js index 7e38b49c792..b14153dbbfa 100644 --- a/spec/javascripts/groups/groups_spec.js +++ b/spec/javascripts/groups/groups_spec.js @@ -2,7 +2,6 @@ import Vue from 'vue'; import eventHub from '~/groups/event_hub'; import groupFolderComponent from '~/groups/components/group_folder.vue'; import groupItemComponent from '~/groups/components/group_item.vue'; -import groupIdenticonComponent from '~/groups/components/group_identicon.vue'; import groupsComponent from '~/groups/components/groups.vue'; import GroupsStore from '~/groups/stores/groups_store'; import { groupsData } from './mock_data'; @@ -15,7 +14,6 @@ describe('Groups Component', () => { beforeEach((done) => { Vue.component('group-folder', groupFolderComponent); - Vue.component('group-identicon', groupIdenticonComponent); Vue.component('group-item', groupItemComponent); store = new GroupsStore(); -- cgit v1.2.1 From 59377d54e91ba9acb309fe3cb1d4f942dbf43e54 Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Tue, 1 Aug 2017 14:38:09 +0530 Subject: Tests for `group_identicon` component --- spec/javascripts/groups/group_identicon_spec.js | 82 +++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 spec/javascripts/groups/group_identicon_spec.js diff --git a/spec/javascripts/groups/group_identicon_spec.js b/spec/javascripts/groups/group_identicon_spec.js new file mode 100644 index 00000000000..d9615646982 --- /dev/null +++ b/spec/javascripts/groups/group_identicon_spec.js @@ -0,0 +1,82 @@ +import Vue from 'vue'; +import groupIdenticonComponent from '~/groups/components/group_identicon.vue'; +import GroupsStore from '~/groups/stores/groups_store'; +import { group1 } from './mock_data'; + +const createComponent = () => { + const Component = Vue.extend(groupIdenticonComponent); + const store = new GroupsStore(); + const group = store.decorateGroup(group1); + + return new Component({ + el: document.createElement('div'), + propsData: { + entityId: group.id, + entityName: group.name, + }, + }); +}; + +describe('GroupIdenticonComponent', () => { + let vm; + let el; + + beforeEach(() => { + vm = createComponent(); + el = vm.$el; + }); + + describe('props', () => { + it('should have props with defined data types', (done) => { + const identiconProps = groupIdenticonComponent.props; + const EntityIdTypeClass = identiconProps.entityId.type; + const EntityNameTypeClass = identiconProps.entityName.type; + + Vue.nextTick(() => { + expect(identiconProps.entityId).toBeDefined(); + expect(new EntityIdTypeClass() instanceof Number).toBeTruthy(); + expect(identiconProps.entityId.required).toBeTruthy(); + + expect(identiconProps.entityName).toBeDefined(); + expect(new EntityNameTypeClass() instanceof String).toBeTruthy(); + expect(identiconProps.entityName.required).toBeTruthy(); + done(); + }); + }); + }); + + describe('computed', () => { + describe('identiconStyles', () => { + it('should return styles attribute value with `background-color` property', () => { + vm.entityId = 4; + + expect(vm.identiconStyles).toBeDefined(); + expect(vm.identiconStyles.indexOf('background-color: #E0F2F1;') > -1).toBeTruthy(); + }); + + it('should return styles attribute value with `color` property', () => { + vm.entityId = 4; + + expect(vm.identiconStyles).toBeDefined(); + expect(vm.identiconStyles.indexOf('color: #555;') > -1).toBeTruthy(); + }); + }); + + describe('identiconTitle', () => { + it('should return first letter of entity title in uppercase', () => { + vm.entityName = 'dummy-group'; + + expect(vm.identiconTitle).toBeDefined(); + expect(vm.identiconTitle).toBe('D'); + }); + }); + }); + + describe('template', () => { + it('should render identicon', () => { + expect(el.nodeName).toBe('DIV'); + expect(el.classList.contains('identicon')).toBeTruthy(); + expect(el.getAttribute('style').indexOf('background-color') > -1).toBeTruthy(); + }); + }); +}); -- cgit v1.2.1 From 00226a9404d8e453a06d09ec54628a4eb66d98ec Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Tue, 1 Aug 2017 14:38:40 +0530 Subject: Import `group_identicon` minor clean up and prop updates --- app/assets/javascripts/groups/components/group_item.vue | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue index c704aa65df2..41c9e5fc8b0 100644 --- a/app/assets/javascripts/groups/components/group_item.vue +++ b/app/assets/javascripts/groups/components/group_item.vue @@ -1,7 +1,11 @@ -- cgit v1.2.1 From 9f8152d84b1778c9d5c693d2cbc12b26cad596c4 Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Tue, 1 Aug 2017 14:40:55 +0530 Subject: Add changelog entry --- changelogs/unreleased/35408-group-auto-avatars.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelogs/unreleased/35408-group-auto-avatars.yml diff --git a/changelogs/unreleased/35408-group-auto-avatars.yml b/changelogs/unreleased/35408-group-auto-avatars.yml new file mode 100644 index 00000000000..77b644a7f94 --- /dev/null +++ b/changelogs/unreleased/35408-group-auto-avatars.yml @@ -0,0 +1,4 @@ +--- +title: Show auto-generated avatars for Groups without avatars +merge_request: 13188 +author: -- cgit v1.2.1 From e7d6af729f14b487a238da3c62c3dbde3b29bbb8 Mon Sep 17 00:00:00 2001 From: kushalpandya Date: Wed, 2 Aug 2017 14:44:46 +0530 Subject: Remove unnecessary name property --- app/assets/javascripts/groups/components/group_identicon.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/groups/components/group_identicon.vue b/app/assets/javascripts/groups/components/group_identicon.vue index ba921a177e9..0edd820743f 100644 --- a/app/assets/javascripts/groups/components/group_identicon.vue +++ b/app/assets/javascripts/groups/components/group_identicon.vue @@ -1,6 +1,5 @@