Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-10 06:08:14 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-10 06:08:14 +0300
commit55bd6d19a7f18f744ba48a9e8f33b5a3ee209a43 (patch)
tree5a2308b16c3db52ae0d22727ac6b1804a440cac2 /app/assets/javascripts/groups
parentedcd73e5fdc11332fc3c974a76ad219928806bfd (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.vue38
-rw-r--r--app/assets/javascripts/groups/components/empty_state.vue91
-rw-r--r--app/assets/javascripts/groups/index.js25
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);