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:
Diffstat (limited to 'app/assets/javascripts/groups')
-rw-r--r--app/assets/javascripts/groups/components/app.vue9
-rw-r--r--app/assets/javascripts/groups/components/item_stats.vue6
-rw-r--r--app/assets/javascripts/groups/components/overview_tabs.vue73
-rw-r--r--app/assets/javascripts/groups/constants.js54
-rw-r--r--app/assets/javascripts/groups/init_overview_tabs.js2
-rw-r--r--app/assets/javascripts/groups/service/archived_projects_service.js56
-rw-r--r--app/assets/javascripts/groups/service/groups_service.js13
-rw-r--r--app/assets/javascripts/groups/settings/init_access_dropdown.js2
8 files changed, 160 insertions, 55 deletions
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index ebfffdaaf50..c6fe16b13b5 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -114,9 +114,9 @@ export default {
showModal() {
this.isModalVisible = true;
},
- fetchGroups({ parentId, page, filterGroupsBy, sortBy, archived, updatePagination }) {
+ fetchGroups({ parentId, page, filterGroupsBy, sortBy, updatePagination }) {
return this.service
- .getGroups(parentId, page, filterGroupsBy, sortBy, archived)
+ .getGroups(parentId, page, filterGroupsBy, sortBy)
.then((res) => {
if (updatePagination) {
this.updatePagination(res.headers);
@@ -133,7 +133,6 @@ export default {
fetchAllGroups() {
const page = getParameterByName('page') || null;
const sortBy = getParameterByName('sort') || null;
- const archived = getParameterByName('archived') || null;
this.isLoading = true;
@@ -141,7 +140,6 @@ export default {
page,
filterGroupsBy: this.filterGroupsBy,
sortBy,
- archived,
updatePagination: true,
}).then((res) => {
this.isLoading = false;
@@ -160,14 +158,13 @@ export default {
this.updateGroups(res, Boolean(filterGroupsBy));
});
},
- fetchPage({ page, filterGroupsBy, sortBy, archived }) {
+ fetchPage({ page, filterGroupsBy, sortBy }) {
this.isLoading = true;
return this.fetchGroups({
page,
filterGroupsBy,
sortBy,
- archived,
updatePagination: true,
}).then((res) => {
this.isLoading = false;
diff --git a/app/assets/javascripts/groups/components/item_stats.vue b/app/assets/javascripts/groups/components/item_stats.vue
index 5674e28f5da..d87190edfd2 100644
--- a/app/assets/javascripts/groups/components/item_stats.vue
+++ b/app/assets/javascripts/groups/components/item_stats.vue
@@ -36,6 +36,9 @@ export default {
<template>
<div class="stats gl-text-gray-500">
+ <div v-if="isProjectPendingRemoval">
+ <gl-badge class="gl-mr-2" variant="warning">{{ __('pending deletion') }}</gl-badge>
+ </div>
<item-stats-value
v-if="displayValue(item.subgroupCount)"
:title="__('Subgroups')"
@@ -65,9 +68,6 @@ export default {
css-class="project-stars"
icon-name="star"
/>
- <div v-if="isProjectPendingRemoval">
- <gl-badge variant="warning">{{ __('pending deletion') }}</gl-badge>
- </div>
<div v-if="isProject" class="last-updated">
<time-ago-tooltip :time="item.lastActivityAt" tooltip-placement="bottom" />
</div>
diff --git a/app/assets/javascripts/groups/components/overview_tabs.vue b/app/assets/javascripts/groups/components/overview_tabs.vue
index 982dab45117..90a0582cc9f 100644
--- a/app/assets/javascripts/groups/components/overview_tabs.vue
+++ b/app/assets/javascripts/groups/components/overview_tabs.vue
@@ -3,13 +3,17 @@ import { GlTabs, GlTab, GlSearchBoxByType, GlSorting, GlSortingItem } from '@git
import { isString, debounce } from 'lodash';
import { __ } from '~/locale';
import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
+import { markRaw } from '~/lib/utils/vue3compat/mark_raw';
import GroupsStore from '../store/groups_store';
import GroupsService from '../service/groups_service';
+import ArchivedProjectsService from '../service/archived_projects_service';
import {
ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
ACTIVE_TAB_SHARED,
ACTIVE_TAB_ARCHIVED,
+ SORTING_ITEM_NAME,
OVERVIEW_TABS_SORTING_ITEMS,
+ OVERVIEW_TABS_ARCHIVED_PROJECTS_SORTING_ITEMS,
} from '../constants';
import eventHub from '../event_hub';
import GroupsApp from './app.vue';
@@ -17,7 +21,6 @@ import SubgroupsAndProjectsEmptyState from './empty_states/subgroups_and_project
import SharedProjectsEmptyState from './empty_states/shared_projects_empty_state.vue';
import ArchivedProjectsEmptyState from './empty_states/archived_projects_empty_state.vue';
-const [SORTING_ITEM_NAME] = OVERVIEW_TABS_SORTING_ITEMS;
const MIN_SEARCH_LENGTH = 3;
export default {
@@ -32,32 +35,38 @@ export default {
SharedProjectsEmptyState,
ArchivedProjectsEmptyState,
},
- inject: ['endpoints', 'initialSort'],
+ inject: ['endpoints', 'initialSort', 'groupId'],
data() {
const tabs = [
{
title: this.$options.i18n[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS],
key: ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
- emptyStateComponent: SubgroupsAndProjectsEmptyState,
+ emptyStateComponent: markRaw(SubgroupsAndProjectsEmptyState),
lazy: this.$route.name !== ACTIVE_TAB_SUBGROUPS_AND_PROJECTS,
- service: new GroupsService(this.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS]),
+ service: new GroupsService(
+ this.endpoints[ACTIVE_TAB_SUBGROUPS_AND_PROJECTS],
+ this.initialSort,
+ ),
store: new GroupsStore({ showSchemaMarkup: true }),
+ sortingItems: OVERVIEW_TABS_SORTING_ITEMS,
},
{
title: this.$options.i18n[ACTIVE_TAB_SHARED],
key: ACTIVE_TAB_SHARED,
- emptyStateComponent: SharedProjectsEmptyState,
+ emptyStateComponent: markRaw(SharedProjectsEmptyState),
lazy: this.$route.name !== ACTIVE_TAB_SHARED,
- service: new GroupsService(this.endpoints[ACTIVE_TAB_SHARED]),
+ service: new GroupsService(this.endpoints[ACTIVE_TAB_SHARED], this.initialSort),
store: new GroupsStore(),
+ sortingItems: OVERVIEW_TABS_SORTING_ITEMS,
},
{
title: this.$options.i18n[ACTIVE_TAB_ARCHIVED],
key: ACTIVE_TAB_ARCHIVED,
- emptyStateComponent: ArchivedProjectsEmptyState,
+ emptyStateComponent: markRaw(ArchivedProjectsEmptyState),
lazy: this.$route.name !== ACTIVE_TAB_ARCHIVED,
- service: new GroupsService(this.endpoints[ACTIVE_TAB_ARCHIVED]),
+ service: new ArchivedProjectsService(this.groupId, this.initialSort),
store: new GroupsStore(),
+ sortingItems: OVERVIEW_TABS_ARCHIVED_PROJECTS_SORTING_ITEMS,
},
];
return {
@@ -79,15 +88,30 @@ export default {
mounted() {
this.search = this.$route.query?.filter || '';
- const sortQueryStringValue = this.$route.query?.sort || this.initialSort;
- const sort =
- OVERVIEW_TABS_SORTING_ITEMS.find((sortOption) =>
- [sortOption.asc, sortOption.desc].includes(sortQueryStringValue),
- ) || SORTING_ITEM_NAME;
+ const { sort, isAscending } = this.getActiveSort();
+
this.sort = sort;
- this.isAscending = sort.asc === sortQueryStringValue;
+ this.isAscending = isAscending;
},
methods: {
+ getActiveSort() {
+ const sortQueryStringValue = this.$route.query?.sort || this.initialSort;
+ const sort = this.activeTab.sortingItems.find((sortOption) =>
+ [sortOption.asc, sortOption.desc].includes(sortQueryStringValue),
+ );
+
+ if (!sort) {
+ return {
+ sort: SORTING_ITEM_NAME,
+ isAscending: true,
+ };
+ }
+
+ return {
+ sort,
+ isAscending: sort.asc === sortQueryStringValue,
+ };
+ },
handleTabInput(tabIndex) {
if (tabIndex === this.activeTabIndex) {
return;
@@ -105,7 +129,23 @@ export default {
? this.$route.params.group.split('/')
: this.$route.params.group;
- this.$router.push({ name: tab.key, params: { group: groupParam }, query: this.$route.query });
+ const { sort, isAscending } = this.getActiveSort();
+
+ this.sort = sort;
+ this.isAscending = isAscending;
+
+ const sortQuery = isAscending ? sort.asc : sort.desc;
+
+ const query = {
+ ...this.$route.query,
+ ...(this.$route.query?.sort && { sort: sortQuery }),
+ };
+
+ this.$router.push({
+ name: tab.key,
+ params: { group: groupParam },
+ query,
+ });
},
handleSearchOrSortChange() {
// Update query string
@@ -164,7 +204,6 @@ export default {
[ACTIVE_TAB_ARCHIVED]: __('Archived projects'),
searchPlaceholder: __('Search'),
},
- OVERVIEW_TABS_SORTING_ITEMS,
};
</script>
@@ -203,7 +242,7 @@ export default {
@sortDirectionChange="handleSortDirectionChange"
>
<gl-sorting-item
- v-for="sortingItem in $options.OVERVIEW_TABS_SORTING_ITEMS"
+ v-for="sortingItem in activeTab.sortingItems"
:key="sortingItem.label"
:active="sortingItem === sort"
@click="handleSortingItemClick(sortingItem)"
diff --git a/app/assets/javascripts/groups/constants.js b/app/assets/javascripts/groups/constants.js
index a5854632040..574ec8e4e49 100644
--- a/app/assets/javascripts/groups/constants.js
+++ b/app/assets/javascripts/groups/constants.js
@@ -25,25 +25,39 @@ export const ITEM_TYPE = {
GROUP: 'group',
};
+export const SORTING_ITEM_NAME = {
+ label: __('Name'),
+ asc: 'name_asc',
+ desc: 'name_desc',
+};
+
+export const SORTING_ITEM_CREATED = {
+ label: __('Created'),
+ asc: 'created_asc',
+ desc: 'created_desc',
+};
+
+export const SORTING_ITEM_UPDATED = {
+ label: __('Updated'),
+ asc: 'latest_activity_asc',
+ desc: 'latest_activity_desc',
+};
+
+export const SORTING_ITEM_STARS = {
+ label: __('Stars'),
+ asc: 'stars_asc',
+ desc: 'stars_desc',
+};
+
export const OVERVIEW_TABS_SORTING_ITEMS = [
- {
- label: __('Name'),
- asc: 'name_asc',
- desc: 'name_desc',
- },
- {
- label: __('Created'),
- asc: 'created_asc',
- desc: 'created_desc',
- },
- {
- label: __('Updated'),
- asc: 'latest_activity_asc',
- desc: 'latest_activity_desc',
- },
- {
- label: __('Stars'),
- asc: 'stars_asc',
- desc: 'stars_desc',
- },
+ SORTING_ITEM_NAME,
+ SORTING_ITEM_CREATED,
+ SORTING_ITEM_UPDATED,
+ SORTING_ITEM_STARS,
+];
+
+export const OVERVIEW_TABS_ARCHIVED_PROJECTS_SORTING_ITEMS = [
+ SORTING_ITEM_NAME,
+ SORTING_ITEM_CREATED,
+ SORTING_ITEM_UPDATED,
];
diff --git a/app/assets/javascripts/groups/init_overview_tabs.js b/app/assets/javascripts/groups/init_overview_tabs.js
index ced5d76d8b9..b831ae7b9d6 100644
--- a/app/assets/javascripts/groups/init_overview_tabs.js
+++ b/app/assets/javascripts/groups/init_overview_tabs.js
@@ -40,6 +40,7 @@ export const initGroupOverviewTabs = () => {
const router = createRouter();
const {
+ groupId,
newSubgroupPath,
newProjectPath,
newSubgroupIllustration,
@@ -59,6 +60,7 @@ export const initGroupOverviewTabs = () => {
el,
router,
provide: {
+ groupId,
newSubgroupPath,
newProjectPath,
newSubgroupIllustration,
diff --git a/app/assets/javascripts/groups/service/archived_projects_service.js b/app/assets/javascripts/groups/service/archived_projects_service.js
new file mode 100644
index 00000000000..5ffa3f91b06
--- /dev/null
+++ b/app/assets/javascripts/groups/service/archived_projects_service.js
@@ -0,0 +1,56 @@
+import Api from '~/api';
+
+export default class ArchivedProjectsService {
+ constructor(groupId, initialSort) {
+ this.groupId = groupId;
+ this.initialSort = initialSort;
+ }
+
+ async getGroups(parentId, page, query, sortParam) {
+ const supportedOrderBy = {
+ name: 'name',
+ created: 'created_at',
+ latest_activity: 'last_activity_at',
+ };
+
+ const [, orderBy, sort] = (sortParam || this.initialSort)?.match(/(\w+)_(asc|desc)/) || [];
+
+ const { data: projects, headers } = await Api.groupProjects(this.groupId, query, {
+ archived: true,
+ page,
+ order_by: supportedOrderBy[orderBy],
+ sort,
+ });
+
+ return {
+ data: projects.map((project) => {
+ return {
+ id: project.id,
+ name: project.name,
+ full_name: project.name_with_namespace,
+ markdown_description: project.description_html,
+ visibility: project.visibility,
+ avatar_url: project.avatar_url,
+ relative_path: `/${project.path_with_namespace}`,
+ edit_path: null,
+ leave_path: null,
+ can_edit: false,
+ can_leave: false,
+ can_remove: false,
+ type: 'project',
+ permission: null,
+ children: [],
+ parent_id: project.namespace.id,
+ project_count: 0,
+ subgroup_count: 0,
+ number_users_with_delimiter: 0,
+ star_count: project.star_count,
+ updated_at: project.updated_at,
+ marked_for_deletion: project.marked_for_deletion_at !== null,
+ last_activity_at: project.last_activity_at,
+ };
+ }),
+ headers,
+ };
+ }
+}
diff --git a/app/assets/javascripts/groups/service/groups_service.js b/app/assets/javascripts/groups/service/groups_service.js
index 790b581a7c0..28d203bc9c6 100644
--- a/app/assets/javascripts/groups/service/groups_service.js
+++ b/app/assets/javascripts/groups/service/groups_service.js
@@ -1,11 +1,12 @@
import axios from '~/lib/utils/axios_utils';
export default class GroupsService {
- constructor(endpoint) {
+ constructor(endpoint, initialSort) {
this.endpoint = endpoint;
+ this.initialSort = initialSort;
}
- getGroups(parentId, page, filterGroups, sort, archived) {
+ getGroups(parentId, page, filterGroups, sort) {
const params = {};
if (parentId) {
@@ -20,12 +21,8 @@ export default class GroupsService {
params.filter = filterGroups;
}
- if (sort) {
- params.sort = sort;
- }
-
- if (archived) {
- params.archived = archived;
+ if (sort || this.initialSort) {
+ params.sort = sort || this.initialSort;
}
}
diff --git a/app/assets/javascripts/groups/settings/init_access_dropdown.js b/app/assets/javascripts/groups/settings/init_access_dropdown.js
index 24419280fc0..4da38e0e641 100644
--- a/app/assets/javascripts/groups/settings/init_access_dropdown.js
+++ b/app/assets/javascripts/groups/settings/init_access_dropdown.js
@@ -4,7 +4,7 @@ import AccessDropdown from './components/access_dropdown.vue';
export const initAccessDropdown = (el) => {
if (!el) {
- return false;
+ return null;
}
const { label, disabled, preselectedItems } = el.dataset;