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>2023-08-04 18:10:27 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-08-04 18:10:27 +0300
commitd984d4a092018d86eec724a06ce2e6c066c3fb44 (patch)
treeb72454a613480658d9b2b14b74eb7b8c75858544 /app/assets/javascripts/vue_shared/components
parent30a8e054751fe9020a9ed526434db83af35b4718 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared/components')
-rw-r--r--app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js19
-rw-r--r--app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue168
3 files changed, 216 insertions, 0 deletions
diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js
new file mode 100644
index 00000000000..235523054c3
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js
@@ -0,0 +1,19 @@
+import { groups } from 'jest/vue_shared/components/groups_list/mock_data';
+import GroupsList from './groups_list.vue';
+
+export default {
+ component: GroupsList,
+ title: 'vue_shared/groups_list',
+};
+
+const Template = (args, { argTypes }) => ({
+ components: { GroupsList },
+ props: Object.keys(argTypes),
+ template: '<groups-list v-bind="$props" />',
+});
+
+export const Default = Template.bind({});
+Default.args = {
+ groups,
+ showGroupIcon: true,
+};
diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue
new file mode 100644
index 00000000000..7da45169fee
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue
@@ -0,0 +1,29 @@
+<script>
+import GroupsListItem from './groups_list_item.vue';
+
+export default {
+ components: { GroupsListItem },
+ props: {
+ groups: {
+ type: Array,
+ required: true,
+ },
+ showGroupIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+};
+</script>
+
+<template>
+ <ul class="gl-p-0 gl-list-style-none">
+ <groups-list-item
+ v-for="group in groups"
+ :key="group.id"
+ :group="group"
+ :show-group-icon="showGroupIcon"
+ />
+ </ul>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue b/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue
new file mode 100644
index 00000000000..8a301cd0dd0
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue
@@ -0,0 +1,168 @@
+<script>
+import { GlAvatarLabeled, GlIcon, GlTooltipDirective, GlTruncateText } from '@gitlab/ui';
+
+import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '~/visibility_level/constants';
+import { ACCESS_LEVEL_LABELS } from '~/access_level/constants';
+import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
+import { __ } from '~/locale';
+import { numberToMetricPrefix } from '~/lib/utils/number_utils';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+
+export default {
+ i18n: {
+ subgroups: __('Subgroups'),
+ projects: __('Projects'),
+ directMembers: __('Direct members'),
+ showMore: __('Show more'),
+ showLess: __('Show less'),
+ },
+ avatarSize: { default: 32, md: 48 },
+ safeHtmlConfig: {
+ ADD_TAGS: ['gl-emoji'],
+ },
+ components: {
+ GlAvatarLabeled,
+ GlIcon,
+ UserAccessRoleBadge,
+ GlTruncateText,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ props: {
+ group: {
+ type: Object,
+ required: true,
+ },
+ showGroupIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ visibility() {
+ return this.group.visibility;
+ },
+ visibilityIcon() {
+ return VISIBILITY_TYPE_ICON[this.visibility];
+ },
+ visibilityTooltip() {
+ return GROUP_VISIBILITY_TYPE[this.visibility];
+ },
+ accessLevel() {
+ return this.group.accessLevel?.integerValue;
+ },
+ accessLevelLabel() {
+ return ACCESS_LEVEL_LABELS[this.accessLevel];
+ },
+ shouldShowAccessLevel() {
+ return this.accessLevel !== undefined;
+ },
+ groupIconName() {
+ return this.group.parent ? 'subgroup' : 'group';
+ },
+ statsPadding() {
+ return this.showGroupIcon ? 'gl-pl-11' : 'gl-pl-8';
+ },
+ descendantGroupsCount() {
+ return numberToMetricPrefix(this.group.descendantGroupsCount);
+ },
+ projectsCount() {
+ return numberToMetricPrefix(this.group.projectsCount);
+ },
+ groupMembersCount() {
+ return numberToMetricPrefix(this.group.groupMembersCount);
+ },
+ },
+};
+</script>
+
+<template>
+ <li class="groups-list-item gl-py-5 gl-md-display-flex gl-align-items-center gl-border-b">
+ <div class="gl-display-flex gl-flex-grow-1">
+ <gl-icon
+ v-if="showGroupIcon"
+ class="gl-mr-3 gl-mt-3 gl-md-mt-5 gl-flex-shrink-0 gl-text-secondary"
+ :name="groupIconName"
+ />
+ <gl-avatar-labeled
+ :entity-id="group.id"
+ :entity-name="group.fullName"
+ :label="group.fullName"
+ :label-link="group.webUrl"
+ shape="rect"
+ :size="$options.avatarSize"
+ >
+ <template #meta>
+ <div class="gl-px-2">
+ <div class="gl-mx-n2 gl-display-flex gl-align-items-center gl-flex-wrap">
+ <div class="gl-px-2">
+ <gl-icon
+ v-if="visibility"
+ v-gl-tooltip="visibilityTooltip"
+ :name="visibilityIcon"
+ class="gl-text-secondary"
+ />
+ </div>
+ <div class="gl-px-2">
+ <user-access-role-badge v-if="shouldShowAccessLevel">{{
+ accessLevelLabel
+ }}</user-access-role-badge>
+ </div>
+ </div>
+ </div>
+ </template>
+ <gl-truncate-text
+ v-if="group.descriptionHtml"
+ :lines="2"
+ :mobile-lines="2"
+ :show-more-text="$options.i18n.showMore"
+ :show-less-text="$options.i18n.showLess"
+ class="gl-mt-2"
+ >
+ <div
+ v-safe-html:[$options.safeHtmlConfig]="group.descriptionHtml"
+ class="gl-font-sm md"
+ data-testid="group-description"
+ ></div>
+ </gl-truncate-text>
+ </gl-avatar-labeled>
+ </div>
+ <div
+ class="gl-md-display-flex gl-flex-direction-column gl-align-items-flex-end gl-flex-shrink-0 gl-mt-3 gl-md-pl-0 gl-md-mt-0 gl-md-ml-3"
+ :class="statsPadding"
+ >
+ <div class="gl-display-flex gl-align-items-center gl-gap-x-3">
+ <div
+ v-gl-tooltip="$options.i18n.subgroups"
+ :aria-label="$options.i18n.subgroups"
+ class="gl-text-secondary"
+ data-testid="subgroups-count"
+ >
+ <gl-icon name="subgroup" />
+ <span>{{ descendantGroupsCount }}</span>
+ </div>
+ <div
+ v-gl-tooltip="$options.i18n.projects"
+ :aria-label="$options.i18n.projects"
+ class="gl-text-secondary"
+ data-testid="projects-count"
+ >
+ <gl-icon name="project" />
+ <span>{{ projectsCount }}</span>
+ </div>
+ <div
+ v-gl-tooltip="$options.i18n.directMembers"
+ :aria-label="$options.i18n.directMembers"
+ class="gl-text-secondary"
+ data-testid="members-count"
+ >
+ <gl-icon name="users" />
+ <span>{{ groupMembersCount }}</span>
+ </div>
+ </div>
+ </div>
+ </li>
+</template>