diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-10 06:08:14 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-10 06:08:14 +0300 |
commit | 55bd6d19a7f18f744ba48a9e8f33b5a3ee209a43 (patch) | |
tree | 5a2308b16c3db52ae0d22727ac6b1804a440cac2 /app/assets/javascripts/groups | |
parent | edcd73e5fdc11332fc3c974a76ad219928806bfd (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/groups')
-rw-r--r-- | app/assets/javascripts/groups/components/app.vue | 38 | ||||
-rw-r--r-- | app/assets/javascripts/groups/components/empty_state.vue | 91 | ||||
-rw-r--r-- | app/assets/javascripts/groups/index.js | 25 |
3 files changed, 145 insertions, 9 deletions
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue index 871cbaf0d1a..cd5521c599e 100644 --- a/app/assets/javascripts/groups/components/app.vue +++ b/app/assets/javascripts/groups/components/app.vue @@ -1,19 +1,26 @@ <script> import { GlLoadingIcon, GlModal } from '@gitlab/ui'; import createFlash from '~/flash'; -import { HIDDEN_CLASS } from '~/lib/utils/constants'; import { mergeUrlParams, getParameterByName } from '~/lib/utils/url_utility'; +import { HIDDEN_CLASS } from '~/lib/utils/constants'; import { __, s__, sprintf } from '~/locale'; import { COMMON_STR, CONTENT_LIST_CLASS } from '../constants'; import eventHub from '../event_hub'; -import groupsComponent from './groups.vue'; +import GroupsComponent from './groups.vue'; +import EmptyState from './empty_state.vue'; export default { components: { - groupsComponent, + GroupsComponent, GlModal, GlLoadingIcon, + EmptyState, + }, + inject: { + renderEmptyState: { + default: false, + }, }, props: { action: { @@ -47,6 +54,7 @@ export default { searchEmptyMessage: '', targetGroup: null, targetParentGroup: null, + showEmptyState: false, }; }, computed: { @@ -75,6 +83,9 @@ export default { pageInfo() { return this.store.getPaginationInfo(); }, + filterGroupsBy() { + return getParameterByName('filter') || null; + }, }, created() { this.searchEmptyMessage = this.hideProjects @@ -128,19 +139,18 @@ export default { const page = getParameterByName('page') || null; const sortBy = getParameterByName('sort') || null; const archived = getParameterByName('archived') || null; - const filterGroupsBy = getParameterByName('filter') || null; this.isLoading = true; return this.fetchGroups({ page, - filterGroupsBy, + filterGroupsBy: this.filterGroupsBy, sortBy, archived, updatePagination: true, }).then((res) => { this.isLoading = false; - this.updateGroups(res, Boolean(filterGroupsBy)); + this.updateGroups(res, Boolean(this.filterGroupsBy)); }); }, fetchPage({ page, filterGroupsBy, sortBy, archived }) { @@ -212,7 +222,7 @@ export default { this.targetGroup.isBeingRemoved = false; }); }, - showEmptyState() { + showLegacyEmptyState() { const { containerEl } = this; const contentListEl = containerEl.querySelector(CONTENT_LIST_CLASS); const emptyStateEl = containerEl.querySelector('.empty-state'); @@ -230,7 +240,12 @@ export default { }, updateGroups(groups, fromSearch) { const hasGroups = groups && groups.length > 0; - this.isSearchEmpty = !hasGroups; + + if (this.renderEmptyState) { + this.isSearchEmpty = this.filterGroupsBy !== null && !hasGroups; + } else { + this.isSearchEmpty = !hasGroups; + } if (fromSearch) { this.store.setSearchedGroups(groups); @@ -239,7 +254,11 @@ export default { } if (this.action && !hasGroups && !fromSearch) { - this.showEmptyState(); + if (this.renderEmptyState) { + this.showEmptyState = true; + } else { + this.showLegacyEmptyState(); + } } }, }, @@ -262,6 +281,7 @@ export default { :page-info="pageInfo" :action="action" /> + <empty-state v-if="showEmptyState" /> <gl-modal modal-id="leave-group-modal" :visible="isModalVisible" diff --git a/app/assets/javascripts/groups/components/empty_state.vue b/app/assets/javascripts/groups/components/empty_state.vue new file mode 100644 index 00000000000..4219b52737d --- /dev/null +++ b/app/assets/javascripts/groups/components/empty_state.vue @@ -0,0 +1,91 @@ +<script> +import { GlLink, GlEmptyState } from '@gitlab/ui'; + +import { s__ } from '~/locale'; + +export default { + components: { GlLink, GlEmptyState }, + i18n: { + withLinks: { + subgroup: { + title: s__('GroupsEmptyState|Create new subgroup'), + description: s__( + 'GroupsEmptyState|Groups are the best way to manage multiple projects and members.', + ), + }, + project: { + title: s__('GroupsEmptyState|Create new project'), + description: s__( + 'GroupsEmptyState|Projects are where you can store your code, access issues, wiki, and other features of Gitlab.', + ), + }, + }, + withoutLinks: { + title: s__('GroupsEmptyState|No subgroups or projects.'), + description: s__( + 'GroupsEmptyState|You do not have necessary permissions to create a subgroup or project in this group. Please contact an owner of this group to create a new subgroup or project.', + ), + }, + }, + linkClasses: [ + 'gl-border', + 'gl-text-decoration-none!', + 'gl-rounded-base', + 'gl-p-7', + 'gl-display-flex', + 'gl-h-full', + 'gl-align-items-center', + 'gl-text-purple-600', + 'gl-hover-bg-gray-50', + ], + inject: [ + 'newSubgroupPath', + 'newProjectPath', + 'newSubgroupIllustration', + 'newProjectIllustration', + 'emptySubgroupIllustration', + 'canCreateSubgroups', + 'canCreateProjects', + ], +}; +</script> + +<template> + <div v-if="canCreateSubgroups || canCreateProjects" class="gl-mt-5"> + <div class="gl-display-flex gl-mx-n3 gl-my-n3 gl-flex-wrap"> + <div v-if="canCreateSubgroups" class="gl-p-3 gl-w-full gl-sm-w-half"> + <gl-link :href="newSubgroupPath" :class="$options.linkClasses"> + <div class="svg-content gl-w-15 gl-flex-shrink-0 gl-mr-5"> + <img :src="newSubgroupIllustration" :alt="$options.i18n.withLinks.subgroup.title" /> + </div> + <div> + <h4 class="gl-reset-color">{{ $options.i18n.withLinks.subgroup.title }}</h4> + <p class="gl-text-body"> + {{ $options.i18n.withLinks.subgroup.description }} + </p> + </div> + </gl-link> + </div> + <div v-if="canCreateProjects" class="gl-p-3 gl-w-full gl-sm-w-half"> + <gl-link :href="newProjectPath" :class="$options.linkClasses"> + <div class="svg-content gl-w-13 gl-flex-shrink-0 gl-mr-5"> + <img :src="newProjectIllustration" :alt="$options.i18n.withLinks.project.title" /> + </div> + <div> + <h4 class="gl-reset-color">{{ $options.i18n.withLinks.project.title }}</h4> + <p class="gl-text-body"> + {{ $options.i18n.withLinks.project.description }} + </p> + </div> + </gl-link> + </div> + </div> + </div> + <gl-empty-state + v-else + class="gl-mt-5" + :title="$options.i18n.withoutLinks.title" + :svg-path="emptySubgroupIllustration" + :description="$options.i18n.withoutLinks.description" + /> +</template> diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js index c34810954a3..dfcee80aec7 100644 --- a/app/assets/javascripts/groups/index.js +++ b/app/assets/javascripts/groups/index.js @@ -44,6 +44,31 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => { components: { groupsApp, }, + provide() { + const { + dataset: { + newSubgroupPath, + newProjectPath, + newSubgroupIllustration, + newProjectIllustration, + emptySubgroupIllustration, + renderEmptyState, + canCreateSubgroups, + canCreateProjects, + }, + } = this.$options.el; + + return { + newSubgroupPath, + newProjectPath, + newSubgroupIllustration, + newProjectIllustration, + emptySubgroupIllustration, + renderEmptyState: parseBoolean(renderEmptyState), + canCreateSubgroups: parseBoolean(canCreateSubgroups), + canCreateProjects: parseBoolean(canCreateProjects), + }; + }, data() { const { dataset } = dataEl || this.$options.el; const hideProjects = parseBoolean(dataset.hideProjects); |