diff options
author | Alfredo Sumaran <alfredo@gitlab.com> | 2017-06-07 03:45:48 -0500 |
---|---|---|
committer | Alfredo Sumaran <alfredo@gitlab.com> | 2017-06-07 04:27:53 -0500 |
commit | f5dfd98856c0fcc8762a38812c71414b3faec951 (patch) | |
tree | 235b78df09637912f2b5484549eacffcd6cbfbc9 | |
parent | 494e80909166157d030bd4f340c7d8a25a249f27 (diff) | |
download | gitlab-ce-f5dfd98856c0fcc8762a38812c71414b3faec951.tar.gz |
Address feedback
-rw-r--r-- | app/assets/javascripts/groups/components/group_folder.vue | 9 | ||||
-rw-r--r-- | app/assets/javascripts/groups/components/group_item.vue | 95 | ||||
-rw-r--r-- | app/assets/javascripts/groups/components/groups.vue | 17 | ||||
-rw-r--r-- | app/assets/javascripts/groups/index.js | 52 | ||||
-rw-r--r-- | app/assets/javascripts/groups/stores/groups_store.js | 2 | ||||
-rw-r--r-- | app/assets/stylesheets/framework/lists.scss | 8 | ||||
-rw-r--r-- | spec/javascripts/groups/group_item_spec.js | 73 | ||||
-rw-r--r-- | spec/javascripts/groups/groups_spec.js | 2 | ||||
-rw-r--r-- | spec/javascripts/groups/mock_data.js | 8 |
9 files changed, 167 insertions, 99 deletions
diff --git a/app/assets/javascripts/groups/components/group_folder.vue b/app/assets/javascripts/groups/components/group_folder.vue index cd47f6b0047..7cc6c4b0359 100644 --- a/app/assets/javascripts/groups/components/group_folder.vue +++ b/app/assets/javascripts/groups/components/group_folder.vue @@ -8,6 +8,7 @@ export default { baseGroup: { type: Object, required: false, + default: () => ({}), }, }, }; @@ -15,6 +16,12 @@ export default { <template> <ul class="content-list group-list-tree"> - <group-item v-for="(group, index) in groups" :key="index" :group="group" :base-group="baseGroup" :collection="groups" /> + <group-item + v-for="(group, index) in groups" + :key="index" + :group="group" + :base-group="baseGroup" + :collection="groups" + /> </ul> </template> diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue index 9fb027e0073..593061a45c6 100644 --- a/app/assets/javascripts/groups/components/group_item.vue +++ b/app/assets/javascripts/groups/components/group_item.vue @@ -102,71 +102,102 @@ export default { :id="groupDomId" :class="rowClass" > - <div class="group-row-contents"> - <div class="controls"> + <div + class="group-row-contents"> + <div + class="controls"> <a v-if="group.canEdit" class="edit-group btn" :href="group.editPath"> <i aria-hidden="true" class="fa fa-cogs"></i> </a> - <a @click="onLeaveGroup" + <a + @click="onLeaveGroup" :href="group.leavePath" class="leave-group btn" title="Leave this group"> - <i aria-hidden="true" class="fa fa-sign-out"></i> + <i + aria-hidden="true" + class="fa fa-sign-out"> + </i> </a> </div> - - <div class="stats"> - <span class="number-projects"> - <i aria-hidden="true" class="fa fa-bookmark"></i> + <div + class="stats"> + <span + class="number-projects"> + <i + aria-hidden="true" + class="fa fa-bookmark"> + </i> {{group.numberProjects}} </span> - <span class="number-users"> - <i aria-hidden="true" class="fa fa-users"></i> + <span + class="number-users"> + <i + aria-hidden="true" + class="fa fa-users"> + </i> {{group.numberUsers}} </span> - <span class="group-visibility"> - <i aria-hidden="true" :class="visibilityIcon"></i> + <span + class="group-visibility"> + <i + aria-hidden="true" + :class="visibilityIcon"> + </i> </span> </div> - - <div class="folder-toggle-wrap"> - <span class="folder-caret" v-if="group.hasSubgroups"> + <div + class="folder-toggle-wrap"> + <span + class="folder-caret" + v-if="group.hasSubgroups"> <i v-if="group.isOpen" - class="fa fa-caret-down" /> + class="fa fa-caret-down"> + </i> <i v-if="!group.isOpen" - class="fa fa-caret-right" /> + class="fa fa-caret-right"> + </i> </span> - <span class="folder-icon"> <i v-if="group.isOpen" class="fa fa-folder-open" - aria-hidden="true"></i> + aria-hidden="true"> + </i> <i v-if="!group.isOpen" - class="fa fa-folder"></i> + class="fa fa-folder" + aria-hidden="true"> + </i> </span> </div> - - <div class="avatar-container s40 hidden-xs"> - <a :href="group.webUrl"> - <img class="avatar s40" :src="group.avatarUrl" /> + <div + class="avatar-container s40 hidden-xs"> + <a + :href="group.webUrl"> + <img + class="avatar s40" + :src="group.avatarUrl" + /> </a> </div> - - <div class="title"> - <a :href="group.webUrl">{{fullPath}}</a> - </div> - - <div class="description"> - {{group.description}} + <div + class="title"> + <a + :href="group.webUrl">{{fullPath}}</a> </div> + <div + class="description">{{group.description}}</div> </div> - <group-folder v-if="group.isOpen && hasGroups" :groups="group.subGroups" :baseGroup="group" /> + <group-folder + v-if="group.isOpen && hasGroups" + :groups="group.subGroups" + :baseGroup="group" + /> </li> </template> diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue index 759b68c8bb4..ad85d84b1e6 100644 --- a/app/assets/javascripts/groups/components/groups.vue +++ b/app/assets/javascripts/groups/components/groups.vue @@ -1,11 +1,8 @@ <script> -import TablePaginationComponent from '~/vue_shared/components/table_pagination.vue'; +import TablePagination from '~/vue_shared/components/table_pagination.vue'; import eventHub from '../event_hub'; export default { - components: { - 'gl-pagination': TablePaginationComponent, - }, props: { groups: { type: Object, @@ -16,6 +13,9 @@ export default { required: true, }, }, + components: { + TablePagination, + }, methods: { change(page) { const filterGroupsParam = gl.utils.getParameterByName('filter_groups'); @@ -28,9 +28,12 @@ export default { <template> <div class="groups-list-tree-container"> - <group-folder :groups="groups" /> - <gl-pagination + <group-folder + :groups="groups" + /> + <table-pagination :change="change" - :pageInfo="pageInfo" /> + :pageInfo="pageInfo" + /> </div> </template> diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js index 885b953f0ee..7dcf5680d18 100644 --- a/app/assets/javascripts/groups/index.js +++ b/app/assets/javascripts/groups/index.js @@ -10,7 +10,7 @@ import GroupsService from './services/groups_service'; import eventHub from './event_hub'; document.addEventListener('DOMContentLoaded', () => { - const el = document.querySelector('#dashboard-group-app'); + const el = document.getElementById('dashboard-group-app'); // Don't do anything if element doesn't exist (No groups) // This is for when the user enters directly to the page via URL @@ -74,27 +74,28 @@ document.addEventListener('DOMContentLoaded', () => { } getGroups = this.service.getGroups(parentId, page, filterGroups, sort); - getGroups.then((response) => { - this.updateGroups(response.json(), parentGroup); - }) - .finally(() => { - this.isLoading = false; - }) - .catch(this.handleErrorResponse); + getGroups + .then(response => response.json()) + .then((response) => { + this.isLoading = false; + + this.updateGroups(response, parentGroup); + }) + .catch(this.handleErrorResponse); return getGroups; }, fetchPage(page, filterGroups, sort) { this.isLoading = true; - this.service.getGroups(null, page, filterGroups, sort) + return this.service + .getGroups(null, page, filterGroups, sort) .then((response) => { + this.isLoading = false; + $.scrollTo(0); + this.updateGroups(response.json()); this.updatePagination(response.headers); - $.scrollTo(0); - }) - .finally(() => { - this.isLoading = false; }) .catch(this.handleErrorResponse); }, @@ -104,19 +105,18 @@ document.addEventListener('DOMContentLoaded', () => { this.fetchGroups(parentGroup); } - GroupsStore.toggleSubGroups(parentGroup); + this.store.toggleSubGroups(parentGroup); }, leaveGroup(group, collection) { this.service.leaveGroup(group.leavePath) .then((response) => { + $.scrollTo(0); + this.store.removeGroup(group, collection); // eslint-disable-next-line no-new new Flash(response.json().notice, 'notice'); }) - .finally(() => { - $.scrollTo(0); - }) .catch((response) => { let message = 'An error occurred. Please try again.'; @@ -135,10 +135,20 @@ document.addEventListener('DOMContentLoaded', () => { this.store.storePagination(headers); }, handleErrorResponse() { + this.isLoading = false; + $.scrollTo(0); + // eslint-disable-next-line no-new new Flash('An error occurred. Please try again.'); }, }, + created() { + eventHub.$on('fetchPage', this.fetchPage); + eventHub.$on('toggleSubGroups', this.toggleSubGroups); + eventHub.$on('leaveGroup', this.leaveGroup); + eventHub.$on('updateGroups', this.updateGroups); + eventHub.$on('updatePagination', this.updatePagination); + }, beforeMount() { let groupFilterList = null; const form = document.querySelector('form#group-filter-form'); @@ -155,19 +165,11 @@ document.addEventListener('DOMContentLoaded', () => { groupFilterList = new GroupFilterableList(opts); groupFilterList.initSearch(); - - eventHub.$on('fetchPage', this.fetchPage); - eventHub.$on('toggleSubGroups', this.toggleSubGroups); - eventHub.$on('leaveGroup', this.leaveGroup); - eventHub.$on('updateGroups', this.updateGroups); - eventHub.$on('updatePagination', this.updatePagination); }, mounted() { this.fetchGroups() .then((response) => { this.updatePagination(response.headers); - }) - .finally(() => { this.isLoading = false; }) .catch(this.handleErrorResponse); diff --git a/app/assets/javascripts/groups/stores/groups_store.js b/app/assets/javascripts/groups/stores/groups_store.js index a10b6617f03..c8f2f161b16 100644 --- a/app/assets/javascripts/groups/stores/groups_store.js +++ b/app/assets/javascripts/groups/stores/groups_store.js @@ -140,7 +140,7 @@ export default class GroupsStore { } // eslint-disable-next-line class-methods-use-this - static toggleSubGroups(toggleGroup) { + toggleSubGroups(toggleGroup) { const group = toggleGroup; group.isOpen = !group.isOpen; return group; diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 88ca1b3311a..666195f9546 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -340,21 +340,21 @@ ul.indent-list { } } } - + .group-row { padding: 0; border: none; } .group-row-contents { - padding: 10px 10px 8px 10px; + padding: 10px 10px 8px; border-top: solid 1px transparent; border-bottom: solid 1px $white-normal; - &:hover{ + &:hover { border-color: $row-hover-border; background-color: $row-hover; - cursor: pointer; + cursor: pointer; } } } diff --git a/spec/javascripts/groups/group_item_spec.js b/spec/javascripts/groups/group_item_spec.js index 47af735f4b4..64b0f31e435 100644 --- a/spec/javascripts/groups/group_item_spec.js +++ b/spec/javascripts/groups/group_item_spec.js @@ -3,39 +3,64 @@ import groupItemComponent from '~/groups/components/group_item.vue'; import GroupsStore from '~/groups/stores/groups_store'; import { group1 } from './mock_data'; -fdescribe('Groups Component', () => { +describe('Groups Component', () => { let GroupItemComponent; let component; let store; let group; - beforeEach((done) => { - GroupItemComponent = Vue.extend(groupItemComponent); - store = new GroupsStore(); - group = store.decorateGroup(group1); + describe('group with default data', () => { + beforeEach((done) => { + GroupItemComponent = Vue.extend(groupItemComponent); + store = new GroupsStore(); + group = store.decorateGroup(group1); - component = new GroupItemComponent({ - propsData: { - group, - }, - }).$mount(); + component = new GroupItemComponent({ + propsData: { + group, + }, + }).$mount(); - Vue.nextTick(() => { - done(); + Vue.nextTick(() => { + done(); + }); }); - }); - it('should render the group item', () => { - expect(component.$el.classList.contains('group-row')).toBe(true); - expect(component.$el.querySelector('.number-projects').textContent).toContain(group.numberProjects); - expect(component.$el.querySelector('.number-users').textContent).toContain(group.numberUsers); - expect(component.$el.querySelector('.group-visibility')).toBeDefined(); - expect(component.$el.querySelector('.avatar-container')).toBeDefined(); - expect(component.$el.querySelector('.title').textContent).toContain(group.name); - expect(component.$el.querySelector('.description').textContent).toContain(group.description); - expect(component.$el.querySelector('.edit-group')).toBeDefined(); - expect(component.$el.querySelector('.leave-group')).toBeDefined(); + it('should render the group item correctly', () => { + expect(component.$el.classList.contains('group-row')).toBe(true); + expect(component.$el.classList.contains('.no-description')).toBe(false); + expect(component.$el.querySelector('.number-projects').textContent).toContain(group.numberProjects); + expect(component.$el.querySelector('.number-users').textContent).toContain(group.numberUsers); + expect(component.$el.querySelector('.group-visibility')).toBeDefined(); + expect(component.$el.querySelector('.avatar-container')).toBeDefined(); + expect(component.$el.querySelector('.title').textContent).toContain(group.name); + expect(component.$el.querySelector('.description').textContent).toContain(group.description); + expect(component.$el.querySelector('.edit-group')).toBeDefined(); + expect(component.$el.querySelector('.leave-group')).toBeDefined(); + }); }); - // TODO: check for no description class when group has no description + describe('group without description', () => { + beforeEach((done) => { + GroupItemComponent = Vue.extend(groupItemComponent); + store = new GroupsStore(); + group1.description = ''; + group = store.decorateGroup(group1); + + component = new GroupItemComponent({ + propsData: { + group, + }, + }).$mount(); + + Vue.nextTick(() => { + done(); + }); + }); + + it('should render group item correctly', () => { + expect(component.$el.querySelector('.description').textContent).toBe(''); + expect(component.$el.classList.contains('.no-description')).toBe(false); + }); + }); }); diff --git a/spec/javascripts/groups/groups_spec.js b/spec/javascripts/groups/groups_spec.js index dc144914c60..d1f900df3d8 100644 --- a/spec/javascripts/groups/groups_spec.js +++ b/spec/javascripts/groups/groups_spec.js @@ -5,7 +5,7 @@ import groupsComponent from '~/groups/components/groups.vue'; import GroupsStore from '~/groups/stores/groups_store'; import { groupsData } from './mock_data'; -fdescribe('Groups Component', () => { +describe('Groups Component', () => { let GroupsComponent; let store; let component; diff --git a/spec/javascripts/groups/mock_data.js b/spec/javascripts/groups/mock_data.js index 98f2aa52135..9951abcc2dc 100644 --- a/spec/javascripts/groups/mock_data.js +++ b/spec/javascripts/groups/mock_data.js @@ -2,7 +2,7 @@ const group1 = { id: '12', name: 'level1', path: 'level1', - description: '', + description: 'foo', visibility: 'public', avatar_url: null, web_url: 'http://localhost:3000/groups/level1', @@ -24,7 +24,7 @@ const group14 = { id: 1128, name: 'level4', path: 'level4', - description: '', + description: 'foo', visibility: 'public', avatar_url: null, web_url: 'http://localhost:3000/groups/level1/level2/level3/level4', @@ -45,7 +45,7 @@ const group2 = { id: 1119, name: 'devops', path: 'devops', - description: '', + description: 'foo', visibility: 'public', avatar_url: null, web_url: 'http://localhost:3000/groups/devops', @@ -66,7 +66,7 @@ const group21 = { id: 1120, name: 'chef', path: 'chef', - description: '', + description: 'foo', visibility: 'public', avatar_url: null, web_url: 'http://localhost:3000/groups/devops/chef', |