diff options
Diffstat (limited to 'app/assets/javascripts/groups')
11 files changed, 197 insertions, 193 deletions
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue index 241e026b84c..e035ba462db 100644 --- a/app/assets/javascripts/groups/components/app.vue +++ b/app/assets/javascripts/groups/components/app.vue @@ -1,16 +1,20 @@ <script> /* global Flash */ +import { s__ } from '~/locale'; +import loadingIcon from '~/vue_shared/components/loading_icon.vue'; +import modal from '~/vue_shared/components/modal.vue'; +import { getParameterByName } from '~/lib/utils/common_utils'; +import { mergeUrlParams } from '~/lib/utils/url_utility'; + import eventHub from '../event_hub'; -import { getParameterByName } from '../../lib/utils/common_utils'; -import loadingIcon from '../../vue_shared/components/loading_icon.vue'; import { COMMON_STR } from '../constants'; -import { mergeUrlParams } from '../../lib/utils/url_utility'; import groupsComponent from './groups.vue'; export default { components: { loadingIcon, + modal, groupsComponent, }, props: { @@ -32,6 +36,10 @@ export default { isLoading: true, isSearchEmpty: false, searchEmptyMessage: '', + showModal: false, + groupLeaveConfirmationMessage: '', + targetGroup: null, + targetParentGroup: null, }; }, computed: { @@ -42,6 +50,26 @@ export default { return this.store.getPaginationInfo(); }, }, + created() { + this.searchEmptyMessage = this.hideProjects ? + COMMON_STR.GROUP_SEARCH_EMPTY : COMMON_STR.GROUP_PROJECT_SEARCH_EMPTY; + + eventHub.$on('fetchPage', this.fetchPage); + eventHub.$on('toggleChildren', this.toggleChildren); + eventHub.$on('showLeaveGroupModal', this.showLeaveGroupModal); + eventHub.$on('updatePagination', this.updatePagination); + eventHub.$on('updateGroups', this.updateGroups); + }, + mounted() { + this.fetchAllGroups(); + }, + beforeDestroy() { + eventHub.$off('fetchPage', this.fetchPage); + eventHub.$off('toggleChildren', this.toggleChildren); + eventHub.$off('showLeaveGroupModal', this.showLeaveGroupModal); + eventHub.$off('updatePagination', this.updatePagination); + eventHub.$off('updateGroups', this.updateGroups); + }, methods: { fetchGroups({ parentId, page, filterGroupsBy, sortBy, archived, updatePagination }) { return this.service.getGroups(parentId, page, filterGroupsBy, sortBy, archived) @@ -121,14 +149,23 @@ export default { parentGroup.isOpen = false; } }, - leaveGroup(group, parentGroup) { - const targetGroup = group; - targetGroup.isBeingRemoved = true; - this.service.leaveGroup(targetGroup.leavePath) + showLeaveGroupModal(group, parentGroup) { + this.targetGroup = group; + this.targetParentGroup = parentGroup; + this.showModal = true; + this.groupLeaveConfirmationMessage = s__(`GroupsTree|Are you sure you want to leave the "${group.fullName}" group?`); + }, + hideLeaveGroupModal() { + this.showModal = false; + }, + leaveGroup() { + this.showModal = false; + this.targetGroup.isBeingRemoved = true; + this.service.leaveGroup(this.targetGroup.leavePath) .then(res => res.json()) .then((res) => { $.scrollTo(0); - this.store.removeGroup(targetGroup, parentGroup); + this.store.removeGroup(this.targetGroup, this.targetParentGroup); Flash(res.notice, 'notice'); }) .catch((err) => { @@ -137,7 +174,7 @@ export default { message = COMMON_STR.LEAVE_FORBIDDEN; } Flash(message); - targetGroup.isBeingRemoved = false; + this.targetGroup.isBeingRemoved = false; }); }, updatePagination(headers) { @@ -152,26 +189,6 @@ export default { } }, }, - created() { - this.searchEmptyMessage = this.hideProjects ? - COMMON_STR.GROUP_SEARCH_EMPTY : COMMON_STR.GROUP_PROJECT_SEARCH_EMPTY; - - eventHub.$on('fetchPage', this.fetchPage); - eventHub.$on('toggleChildren', this.toggleChildren); - eventHub.$on('leaveGroup', this.leaveGroup); - eventHub.$on('updatePagination', this.updatePagination); - eventHub.$on('updateGroups', this.updateGroups); - }, - mounted() { - this.fetchAllGroups(); - }, - beforeDestroy() { - eventHub.$off('fetchPage', this.fetchPage); - eventHub.$off('toggleChildren', this.toggleChildren); - eventHub.$off('leaveGroup', this.leaveGroup); - eventHub.$off('updatePagination', this.updatePagination); - eventHub.$off('updateGroups', this.updateGroups); - }, }; </script> @@ -190,5 +207,14 @@ export default { :search-empty-message="searchEmptyMessage" :page-info="pageInfo" /> + <modal + v-show="showModal" + :primary-button-label="__('Leave')" + kind="warning" + :title="__('Are you sure?')" + :text="groupLeaveConfirmationMessage" + @cancel="hideLeaveGroupModal" + @submit="leaveGroup" + /> </div> </template> diff --git a/app/assets/javascripts/groups/components/group_folder.vue b/app/assets/javascripts/groups/components/group_folder.vue index e60221fa08d..647c9d0046d 100644 --- a/app/assets/javascripts/groups/components/group_folder.vue +++ b/app/assets/javascripts/groups/components/group_folder.vue @@ -20,7 +20,11 @@ export default { return this.parentGroup.childrenCount > MAX_CHILDREN_COUNT; }, moreChildrenStats() { - return n__('One more item', '%d more items', this.parentGroup.childrenCount - this.parentGroup.children.length); + return n__( + 'One more item', + '%d more items', + this.parentGroup.childrenCount - this.parentGroup.children.length, + ); }, }, }; @@ -43,8 +47,9 @@ export default { <i class="fa fa-external-link" aria-hidden="true" - /> - {{moreChildrenStats}} + > + </i> + {{ moreChildrenStats }} </a> </li> </ul> diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue index 42e79a9e17a..764b130fdb8 100644 --- a/app/assets/javascripts/groups/components/group_item.vue +++ b/app/assets/javascripts/groups/components/group_item.vue @@ -75,7 +75,7 @@ export default { :id="groupDomId" :class="rowClass" class="group-row" - > + > <div class="group-row-contents" :class="{ 'project-row-contents': !isGroup }"> @@ -88,7 +88,8 @@ export default { :item="group" /> <div - class="folder-toggle-wrap"> + class="folder-toggle-wrap" + > <item-caret :is-group-open="group.isOpen" /> @@ -113,13 +114,14 @@ export default { <identicon v-else size-class="s24" - :entity-id=group.id + :entity-id="group.id" :entity-name="group.name" /> </a> </div> <div - class="title namespace-title"> + class="title namespace-title" + > <a v-tooltip :href="group.relativePath" @@ -135,7 +137,7 @@ export default { v-if="group.permission" class="user-access-role" > - {{group.permission}} + {{ group.permission }} </span> </div> <div diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue index 75a2bf34887..adde8c8cdb3 100644 --- a/app/assets/javascripts/groups/components/groups.vue +++ b/app/assets/javascripts/groups/components/groups.vue @@ -1,47 +1,48 @@ <script> -import tablePagination from '~/vue_shared/components/table_pagination.vue'; -import eventHub from '../event_hub'; -import { getParameterByName } from '../../lib/utils/common_utils'; + import tablePagination from '~/vue_shared/components/table_pagination.vue'; + import eventHub from '../event_hub'; + import { getParameterByName } from '../../lib/utils/common_utils'; -export default { - components: { - tablePagination, - }, - props: { - groups: { - type: Array, - required: true, + export default { + components: { + tablePagination, }, - pageInfo: { - type: Object, - required: true, + props: { + groups: { + type: Array, + required: true, + }, + pageInfo: { + type: Object, + required: true, + }, + searchEmpty: { + type: Boolean, + required: true, + }, + searchEmptyMessage: { + type: String, + required: true, + }, }, - searchEmpty: { - type: Boolean, - required: true, + methods: { + change(page) { + const filterGroupsParam = getParameterByName('filter_groups'); + const sortParam = getParameterByName('sort'); + const archivedParam = getParameterByName('archived'); + eventHub.$emit('fetchPage', page, filterGroupsParam, sortParam, archivedParam); + }, }, - searchEmptyMessage: { - type: String, - required: true, - }, - }, - methods: { - change(page) { - const filterGroupsParam = getParameterByName('filter_groups'); - const sortParam = getParameterByName('sort'); - const archivedParam = getParameterByName('archived'); - eventHub.$emit('fetchPage', page, filterGroupsParam, sortParam, archivedParam); - }, - }, -}; + }; </script> <template> <div class="groups-list-tree-container"> <div v-if="searchEmpty" - class="has-no-search-results"> - {{searchEmptyMessage}} + class="has-no-search-results" + > + {{ searchEmptyMessage }} </div> <group-folder v-if="!searchEmpty" @@ -50,7 +51,7 @@ export default { <table-pagination v-if="!searchEmpty" :change="change" - :pageInfo="pageInfo" + :page-info="pageInfo" /> </div> </template> diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue index 0dd0783ce06..87065b3d6e3 100644 --- a/app/assets/javascripts/groups/components/item_actions.vue +++ b/app/assets/javascripts/groups/components/item_actions.vue @@ -1,15 +1,12 @@ <script> -import { s__ } from '~/locale'; import tooltip from '~/vue_shared/directives/tooltip'; import icon from '~/vue_shared/components/icon.vue'; -import modal from '~/vue_shared/components/modal.vue'; import eventHub from '../event_hub'; import { COMMON_STR } from '../constants'; export default { components: { icon, - modal, }, directives: { tooltip, @@ -25,11 +22,6 @@ export default { required: true, }, }, - data() { - return { - modalStatus: false, - }; - }, computed: { leaveBtnTitle() { return COMMON_STR.LEAVE_BTN_TITLE; @@ -37,17 +29,10 @@ export default { editBtnTitle() { return COMMON_STR.EDIT_BTN_TITLE; }, - leaveConfirmationMessage() { - return s__(`GroupsTree|Are you sure you want to leave the "${this.group.fullName}" group?`); - }, }, methods: { onLeaveGroup() { - this.modalStatus = true; - }, - leaveGroup() { - this.modalStatus = false; - eventHub.$emit('leaveGroup', this.group, this.parentGroup); + eventHub.$emit('showLeaveGroupModal', this.group, this.parentGroup); }, }, }; @@ -78,14 +63,5 @@ export default { class="leave-group btn no-expand"> <icon name="leave"/> </a> - <modal - v-show="modalStatus" - :primary-button-label="__('Leave')" - kind="warning" - :title="__('Are you sure?')" - :text="__('Are you sure you want to leave this group?')" - :body="leaveConfirmationMessage" - @submit="leaveGroup" - /> </div> </template> diff --git a/app/assets/javascripts/groups/components/item_caret.vue b/app/assets/javascripts/groups/components/item_caret.vue index 9e90fe2b701..2a5bec5e86c 100644 --- a/app/assets/javascripts/groups/components/item_caret.vue +++ b/app/assets/javascripts/groups/components/item_caret.vue @@ -2,6 +2,9 @@ import icon from '~/vue_shared/components/icon.vue'; export default { + components: { + icon, + }, props: { isGroupOpen: { type: Boolean, @@ -9,9 +12,6 @@ export default { default: false, }, }, - components: { - icon, - }, computed: { iconClass() { return this.isGroupOpen ? 'angle-down' : 'angle-right'; diff --git a/app/assets/javascripts/groups/components/item_stats.vue b/app/assets/javascripts/groups/components/item_stats.vue index 2e42fb6c9a6..168b4e4af2c 100644 --- a/app/assets/javascripts/groups/components/item_stats.vue +++ b/app/assets/javascripts/groups/components/item_stats.vue @@ -1,39 +1,44 @@ <script> -import icon from '~/vue_shared/components/icon.vue'; -import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; -import { ITEM_TYPE, VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE, PROJECT_VISIBILITY_TYPE } from '../constants'; -import itemStatsValue from './item_stats_value.vue'; + import icon from '~/vue_shared/components/icon.vue'; + import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; + import { + ITEM_TYPE, + VISIBILITY_TYPE_ICON, + GROUP_VISIBILITY_TYPE, + PROJECT_VISIBILITY_TYPE, + } from '../constants'; + import itemStatsValue from './item_stats_value.vue'; -export default { - components: { - icon, - timeAgoTooltip, - itemStatsValue, - }, - props: { - item: { - type: Object, - required: true, + export default { + components: { + icon, + timeAgoTooltip, + itemStatsValue, }, - }, - computed: { - visibilityIcon() { - return VISIBILITY_TYPE_ICON[this.item.visibility]; + props: { + item: { + type: Object, + required: true, + }, }, - visibilityTooltip() { - if (this.item.type === ITEM_TYPE.GROUP) { - return GROUP_VISIBILITY_TYPE[this.item.visibility]; - } - return PROJECT_VISIBILITY_TYPE[this.item.visibility]; + computed: { + visibilityIcon() { + return VISIBILITY_TYPE_ICON[this.item.visibility]; + }, + visibilityTooltip() { + if (this.item.type === ITEM_TYPE.GROUP) { + return GROUP_VISIBILITY_TYPE[this.item.visibility]; + } + return PROJECT_VISIBILITY_TYPE[this.item.visibility]; + }, + isProject() { + return this.item.type === ITEM_TYPE.PROJECT; + }, + isGroup() { + return this.item.type === ITEM_TYPE.GROUP; + }, }, - isProject() { - return this.item.type === ITEM_TYPE.PROJECT; - }, - isGroup() { - return this.item.type === ITEM_TYPE.GROUP; - }, - }, -}; + }; </script> <template> diff --git a/app/assets/javascripts/groups/components/item_stats_value.vue b/app/assets/javascripts/groups/components/item_stats_value.vue index f441cabf6d2..08d0bf6e344 100644 --- a/app/assets/javascripts/groups/components/item_stats_value.vue +++ b/app/assets/javascripts/groups/components/item_stats_value.vue @@ -1,52 +1,52 @@ <script> -import tooltip from '~/vue_shared/directives/tooltip'; -import icon from '~/vue_shared/components/icon.vue'; + import tooltip from '~/vue_shared/directives/tooltip'; + import icon from '~/vue_shared/components/icon.vue'; -export default { - props: { - title: { - type: String, - required: false, - default: '', + export default { + components: { + icon, }, - cssClass: { - type: String, - required: false, - default: '', + directives: { + tooltip, }, - iconName: { - type: String, - required: true, + props: { + title: { + type: String, + required: false, + default: '', + }, + cssClass: { + type: String, + required: false, + default: '', + }, + iconName: { + type: String, + required: true, + }, + tooltipPlacement: { + type: String, + required: false, + default: 'bottom', + }, + /** + * value could either be number or string + * as `memberCount` is always passed as string + * while `subgroupCount` & `projectCount` + * are always number + */ + value: { + type: [Number, String], + required: false, + default: '', + }, }, - tooltipPlacement: { - type: String, - required: false, - default: 'bottom', + computed: { + isValuePresent() { + return this.value !== ''; + }, }, - /** - * value could either be number or string - * as `memberCount` is always passed as string - * while `subgroupCount` & `projectCount` - * are always number - */ - value: { - type: [Number, String], - required: false, - default: '', - }, - }, - directives: { - tooltip, - }, - components: { - icon, - }, - computed: { - isValuePresent() { - return this.value !== ''; - }, - }, -}; + }; </script> <template> @@ -57,12 +57,12 @@ export default { :class="cssClass" :title="title" > - <icon :name="iconName"/> + <icon :name="iconName" /> <span v-if="isValuePresent" class="stat-value" > - {{value}} + {{ value }} </span> </span> </template> diff --git a/app/assets/javascripts/groups/groups_filterable_list.js b/app/assets/javascripts/groups/groups_filterable_list.js index 2db233b09da..31d56d15c23 100644 --- a/app/assets/javascripts/groups/groups_filterable_list.js +++ b/app/assets/javascripts/groups/groups_filterable_list.js @@ -1,6 +1,6 @@ import FilterableList from '~/filterable_list'; import eventHub from './event_hub'; -import { getParameterByName } from '../lib/utils/common_utils'; +import { normalizeHeaders, getParameterByName } from '../lib/utils/common_utils'; export default class GroupFilterableList extends FilterableList { constructor({ form, filter, holder, filterEndpoint, pagePath, dropdownSel, filterInputField }) { @@ -94,23 +94,14 @@ export default class GroupFilterableList extends FilterableList { this.form.querySelector(`[name="${this.filterInputField}"]`).value = ''; } - onFilterSuccess(data, xhr, queryData) { + onFilterSuccess(res, queryData) { const currentPath = this.getPagePath(queryData); - const paginationData = { - 'X-Per-Page': xhr.getResponseHeader('X-Per-Page'), - 'X-Page': xhr.getResponseHeader('X-Page'), - 'X-Total': xhr.getResponseHeader('X-Total'), - 'X-Total-Pages': xhr.getResponseHeader('X-Total-Pages'), - 'X-Next-Page': xhr.getResponseHeader('X-Next-Page'), - 'X-Prev-Page': xhr.getResponseHeader('X-Prev-Page'), - }; - window.history.replaceState({ page: currentPath, }, document.title, currentPath); - eventHub.$emit('updateGroups', data, Object.prototype.hasOwnProperty.call(queryData, this.filterInputField)); - eventHub.$emit('updatePagination', paginationData); + eventHub.$emit('updateGroups', res.data, Object.prototype.hasOwnProperty.call(queryData, this.filterInputField)); + eventHub.$emit('updatePagination', normalizeHeaders(res.headers)); } } diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js index 8b850765a1b..57eaac72906 100644 --- a/app/assets/javascripts/groups/index.js +++ b/app/assets/javascripts/groups/index.js @@ -10,7 +10,7 @@ import groupItemComponent from './components/group_item.vue'; Vue.use(Translate); -document.addEventListener('DOMContentLoaded', () => { +export default () => { const el = document.getElementById('js-groups-tree'); // Don't do anything if element doesn't exist (No groups) @@ -71,4 +71,4 @@ document.addEventListener('DOMContentLoaded', () => { }); }, }); -}); +}; diff --git a/app/assets/javascripts/groups/service/groups_service.js b/app/assets/javascripts/groups/service/groups_service.js index 639410384c2..b79ba291463 100644 --- a/app/assets/javascripts/groups/service/groups_service.js +++ b/app/assets/javascripts/groups/service/groups_service.js @@ -1,7 +1,5 @@ import Vue from 'vue'; -import VueResource from 'vue-resource'; - -Vue.use(VueResource); +import '../../vue_shared/vue_resource_interceptor'; export default class GroupsService { constructor(endpoint) { |