From d8403ec18f771c28eb566dc3ce6dc08bffd2db22 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Tue, 6 Jun 2017 09:01:42 -0500 Subject: [PATCH] Minor visual adjustments --- .../groups/components/group_folder.vue | 2 +- .../groups/components/group_item.vue | 9 ++- app/assets/javascripts/groups/index.js | 63 ++++++++++++++----- .../javascripts/groups/stores/groups_store.js | 7 +++ app/assets/stylesheets/framework/lists.scss | 7 +++ .../concerns/membership_actions.rb | 2 +- app/views/dashboard/groups/_groups.html.haml | 8 ++- spec/javascripts/groups/group_item_spec.js | 2 +- spec/javascripts/groups/groups_spec.js | 2 +- 9 files changed, 80 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/groups/components/group_folder.vue b/app/assets/javascripts/groups/components/group_folder.vue index dcf6f10e1ca..cd47f6b0047 100644 --- a/app/assets/javascripts/groups/components/group_folder.vue +++ b/app/assets/javascripts/groups/components/group_folder.vue @@ -15,6 +15,6 @@ export default { diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue index 2013469f9e6..c4b0325fb09 100644 --- a/app/assets/javascripts/groups/components/group_item.vue +++ b/app/assets/javascripts/groups/components/group_item.vue @@ -12,6 +12,11 @@ export default { required: false, default: () => ({}), }, + collection: { + type: Object, + required: false, + default: () => ({}), + }, }, methods: { onClickRowGroup(e) { @@ -35,7 +40,7 @@ export default { } }, leaveGroup() { - eventHub.$emit('leaveGroup', this.group.leavePath); + eventHub.$emit('leaveGroup', this.group, this.collection); }, }, computed: { @@ -63,7 +68,7 @@ export default { if (this.group.isOrphan) { // check if current group is baseGroup - if (Object.keys(this.baseGroup).length > 0) { + if (Object.keys(this.baseGroup).length > 0 && this.baseGroup !== this.group) { // Remove baseGroup prefix from our current group.fullName. e.g: // baseGroup.fullName: `level1` // group.fullName: `level1 / level2 / level3` diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js index 9c2e37dd5f1..4e2cb88eb4e 100644 --- a/app/assets/javascripts/groups/index.js +++ b/app/assets/javascripts/groups/index.js @@ -1,3 +1,5 @@ +/* global Flash */ + import Vue from 'vue'; import GroupFilterableList from './groups_filterable_list'; import GroupsComponent from './components/groups.vue'; @@ -29,9 +31,16 @@ document.addEventListener('DOMContentLoaded', () => { return { store: this.store, + isLoading: true, state: this.store.state, + loading: true, }; }, + computed: { + isEmpty() { + return Object.keys(this.state.groups).length === 0; + }, + }, methods: { fetchGroups(parentGroup) { let parentId = null; @@ -43,6 +52,8 @@ document.addEventListener('DOMContentLoaded', () => { let filterGroups = null; let filterGroupsParam = null; + this.isLoading = true; + if (parentGroup) { parentId = parentGroup.id; } @@ -66,22 +77,26 @@ document.addEventListener('DOMContentLoaded', () => { getGroups.then((response) => { this.updateGroups(response.json(), parentGroup); }) - .catch(() => { - // TODO: Handle error - }); + .finally(() => { + this.isLoading = false; + }) + .catch(this.handleErrorResponse); return getGroups; }, fetchPage(page, filterGroups, sort) { + this.isLoading = true; + this.service.getGroups(null, page, filterGroups, sort) .then((response) => { this.updateGroups(response.json()); this.updatePagination(response.headers); $.scrollTo(0); }) - .catch(() => { - // TODO: Handle error - }); + .finally(() => { + this.isLoading = false; + }) + .catch(this.handleErrorResponse); }, toggleSubGroups(parentGroup = null) { if (!parentGroup.isOpen) { @@ -91,13 +106,26 @@ document.addEventListener('DOMContentLoaded', () => { GroupsStore.toggleSubGroups(parentGroup); }, - leaveGroup(endpoint) { - this.service.leaveGroup(endpoint) - .then(() => { - // TODO: Refresh? + leaveGroup(group, collection) { + this.service.leaveGroup(group.leavePath) + .then((response) => { + this.store.removeGroup(group, collection); + + // eslint-disable-next-line no-new + new Flash(response.json().notice, 'notice'); }) - .catch(() => { - // TODO: Handle error + .finally(() => { + $.scrollTo(0); + }) + .catch((response) => { + let message = 'An error occurred. Please try again.'; + + if (response.status === 403) { + message = 'Failed to leave the group. Please make sure you are not the only owner'; + } + + // eslint-disable-next-line no-new + new Flash(message); }); }, updateGroups(groups, parentGroup) { @@ -106,6 +134,10 @@ document.addEventListener('DOMContentLoaded', () => { updatePagination(headers) { this.store.storePagination(headers); }, + handleErrorResponse() { + // eslint-disable-next-line no-new + new Flash('An error occurred. Please try again.'); + }, }, beforeMount() { let groupFilterList = null; @@ -135,9 +167,10 @@ document.addEventListener('DOMContentLoaded', () => { .then((response) => { this.updatePagination(response.headers); }) - .catch(() => { - // TODO: Handle error - }); + .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 d8353a92881..0493cee2fa8 100644 --- a/app/assets/javascripts/groups/stores/groups_store.js +++ b/app/assets/javascripts/groups/stores/groups_store.js @@ -1,3 +1,5 @@ +import Vue from 'vue'; + export default class GroupsStore { constructor() { this.state = {}; @@ -131,6 +133,11 @@ export default class GroupsStore { }; } + // eslint-disable-next-line class-methods-use-this + removeGroup(group, collection) { + Vue.delete(collection, group.id); + } + // eslint-disable-next-line class-methods-use-this static toggleSubGroups(toggleGroup) { const group = toggleGroup; diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index 6d262a63d81..7529538b4a7 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -342,3 +342,10 @@ ul.indent-list { } } } + +.js-groups-list-holder { + .groups-list-loading { + font-size: 34px; + text-align: center; + } +} diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb index f55f03972a9..19fd4e6e2a9 100644 --- a/app/controllers/concerns/membership_actions.rb +++ b/app/controllers/concerns/membership_actions.rb @@ -57,7 +57,7 @@ module MembershipActions redirect_to redirect_path, notice: notice end - format.json { head :ok } + format.json { render json: { notice: notice } } end end diff --git a/app/views/dashboard/groups/_groups.html.haml b/app/views/dashboard/groups/_groups.html.haml index b72b04479de..ba7e0c21348 100644 --- a/app/views/dashboard/groups/_groups.html.haml +++ b/app/views/dashboard/groups/_groups.html.haml @@ -1,3 +1,9 @@ .js-groups-list-holder #dashboard-group-app{ data: { endpoint: dashboard_groups_path(format: :json), path: dashboard_groups_path } } - %groups-component{ ':groups' => 'state.groups', ':page-info' => 'state.pageInfo' } + .groups-list-loading + = icon('spinner spin', 'v-show' => 'isLoading') + %template{ 'v-if' => '!isLoading && isEmpty' } + %div{ 'v-cloak' => true } + = render 'empty_state' + %template{ 'v-else-if' => '!isLoading && !isEmpty'} + %groups-component{ ':groups' => 'state.groups', ':page-info' => 'state.pageInfo' } diff --git a/spec/javascripts/groups/group_item_spec.js b/spec/javascripts/groups/group_item_spec.js index 609c45250f1..47af735f4b4 100644 --- a/spec/javascripts/groups/group_item_spec.js +++ b/spec/javascripts/groups/group_item_spec.js @@ -3,7 +3,7 @@ import groupItemComponent from '~/groups/components/group_item.vue'; import GroupsStore from '~/groups/stores/groups_store'; import { group1 } from './mock_data'; -describe('Groups Component', () => { +fdescribe('Groups Component', () => { let GroupItemComponent; let component; let store; diff --git a/spec/javascripts/groups/groups_spec.js b/spec/javascripts/groups/groups_spec.js index d1f900df3d8..dc144914c60 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'; -describe('Groups Component', () => { +fdescribe('Groups Component', () => { let GroupsComponent; let store; let component;