Commit a378e3b9 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '322395-hide-archived-projects-from-select-project' into 'master'

Hide archived projects when creating a new issue in group boards

See merge request gitlab-org/gitlab!56452
parents 8cfe7d61 8a9609d4
...@@ -7,7 +7,7 @@ import { ...@@ -7,7 +7,7 @@ import {
GlIntersectionObserver, GlIntersectionObserver,
GlLoadingIcon, GlLoadingIcon,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants'; import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
import { ListType } from '../constants'; import { ListType } from '../constants';
...@@ -49,7 +49,8 @@ export default { ...@@ -49,7 +49,8 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(['groupProjects', 'groupProjectsFlags']), ...mapState(['groupProjectsFlags']),
...mapGetters(['activeGroupProjects']),
selectedProjectName() { selectedProjectName() {
return this.selectedProject.name || this.$options.i18n.dropdownText; return this.selectedProject.name || this.$options.i18n.dropdownText;
}, },
...@@ -65,7 +66,7 @@ export default { ...@@ -65,7 +66,7 @@ export default {
}; };
}, },
isFetchResultEmpty() { isFetchResultEmpty() {
return this.groupProjects.length === 0; return this.activeGroupProjects.length === 0;
}, },
hasNextPage() { hasNextPage() {
return this.groupProjectsFlags.pageInfo?.hasNextPage; return this.groupProjectsFlags.pageInfo?.hasNextPage;
...@@ -84,7 +85,7 @@ export default { ...@@ -84,7 +85,7 @@ export default {
methods: { methods: {
...mapActions(['fetchGroupProjects', 'setSelectedProject']), ...mapActions(['fetchGroupProjects', 'setSelectedProject']),
selectProject(projectId) { selectProject(projectId) {
this.selectedProject = this.groupProjects.find((project) => project.id === projectId); this.selectedProject = this.activeGroupProjects.find((project) => project.id === projectId);
this.setSelectedProject(this.selectedProject); this.setSelectedProject(this.selectedProject);
}, },
loadMoreProjects() { loadMoreProjects() {
...@@ -113,7 +114,7 @@ export default { ...@@ -113,7 +114,7 @@ export default {
:placeholder="$options.i18n.searchPlaceholder" :placeholder="$options.i18n.searchPlaceholder"
/> />
<gl-dropdown-item <gl-dropdown-item
v-for="project in groupProjects" v-for="project in activeGroupProjects"
v-show="!groupProjectsFlags.isLoading" v-show="!groupProjectsFlags.isLoading"
:key="project.id" :key="project.id"
:name="project.name" :name="project.name"
......
...@@ -25,6 +25,7 @@ export default { ...@@ -25,6 +25,7 @@ export default {
with_shared: false, with_shared: false,
include_subgroups: true, include_subgroups: true,
order_by: 'similarity', order_by: 'similarity',
archived: false,
}, },
components: { components: {
GlLoadingIcon, GlLoadingIcon,
......
...@@ -8,6 +8,7 @@ query getGroupProjects($fullPath: ID!, $search: String, $after: String) { ...@@ -8,6 +8,7 @@ query getGroupProjects($fullPath: ID!, $search: String, $after: String) {
name name
fullPath fullPath
nameWithNamespace nameWithNamespace
archived
} }
pageInfo { pageInfo {
...PageInfo ...PageInfo
......
...@@ -29,6 +29,10 @@ export default { ...@@ -29,6 +29,10 @@ export default {
return referencePath.slice(0, referencePath.indexOf('#')); return referencePath.slice(0, referencePath.indexOf('#'));
}, },
activeGroupProjects: (state) => {
return state.groupProjects.filter((p) => !p.archived);
},
getListByLabelId: (state) => (labelId) => { getListByLabelId: (state) => (labelId) => {
if (!labelId) { if (!labelId) {
return null; return null;
......
---
title: Hide archived projects from group boards project select dropdown
merge_request: 56452
author:
type: changed
...@@ -351,6 +351,7 @@ export const issues = { ...@@ -351,6 +351,7 @@ export const issues = {
[mockIssue4.id]: mockIssue4, [mockIssue4.id]: mockIssue4,
}; };
// The response from group project REST API
export const mockRawGroupProjects = [ export const mockRawGroupProjects = [
{ {
id: 0, id: 0,
...@@ -366,17 +367,34 @@ export const mockRawGroupProjects = [ ...@@ -366,17 +367,34 @@ export const mockRawGroupProjects = [
}, },
]; ];
export const mockGroupProjects = [ // The response from GraphQL endpoint
{ export const mockGroupProject1 = {
id: 0, id: 0,
name: 'Example Project', name: 'Example Project',
nameWithNamespace: 'Awesome Group / Example Project', nameWithNamespace: 'Awesome Group / Example Project',
fullPath: 'awesome-group/example-project', fullPath: 'awesome-group/example-project',
}, archived: false,
{ };
id: 1,
name: 'Foobar Project', export const mockGroupProject2 = {
nameWithNamespace: 'Awesome Group / Foobar Project', id: 1,
fullPath: 'awesome-group/foobar-project', name: 'Foobar Project',
}, nameWithNamespace: 'Awesome Group / Foobar Project',
fullPath: 'awesome-group/foobar-project',
archived: false,
};
export const mockArchivedGroupProject = {
id: 2,
name: 'Archived Project',
nameWithNamespace: 'Awesome Group / Archived Project',
fullPath: 'awesome-group/archived-project',
archived: true,
};
export const mockGroupProjects = [mockGroupProject1, mockGroupProject2];
export const mockActiveGroupProjects = [
{ ...mockGroupProject1, archived: false },
{ ...mockGroupProject2, archived: false },
]; ];
...@@ -27,6 +27,7 @@ const mockDefaultFetchOptions = { ...@@ -27,6 +27,7 @@ const mockDefaultFetchOptions = {
with_shared: false, with_shared: false,
include_subgroups: true, include_subgroups: true,
order_by: 'similarity', order_by: 'similarity',
archived: false,
}; };
const itemsPerPage = 20; const itemsPerPage = 20;
......
import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui'; import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui';
import { createLocalVue, mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex'; import Vuex from 'vuex';
import ProjectSelect from '~/boards/components/project_select.vue'; import ProjectSelect from '~/boards/components/project_select.vue';
import defaultState from '~/boards/stores/state'; import defaultState from '~/boards/stores/state';
import { mockList, mockGroupProjects } from './mock_data'; import { mockList, mockActiveGroupProjects } from './mock_data';
const localVue = createLocalVue(); const mockProjectsList1 = mockActiveGroupProjects.slice(0, 1);
localVue.use(Vuex);
const actions = {
fetchGroupProjects: jest.fn(),
setSelectedProject: jest.fn(),
};
const createStore = (state = defaultState) => {
return new Vuex.Store({
state,
actions,
});
};
const mockProjectsList1 = mockGroupProjects.slice(0, 1);
describe('ProjectSelect component', () => { describe('ProjectSelect component', () => {
let wrapper; let wrapper;
let store;
const findLabel = () => wrapper.find("[data-testid='header-label']"); const findLabel = () => wrapper.find("[data-testid='header-label']");
const findGlDropdown = () => wrapper.find(GlDropdown); const findGlDropdown = () => wrapper.find(GlDropdown);
...@@ -36,20 +23,37 @@ describe('ProjectSelect component', () => { ...@@ -36,20 +23,37 @@ describe('ProjectSelect component', () => {
const findInMenuLoadingIcon = () => wrapper.find("[data-testid='dropdown-text-loading-icon']"); const findInMenuLoadingIcon = () => wrapper.find("[data-testid='dropdown-text-loading-icon']");
const findEmptySearchMessage = () => wrapper.find("[data-testid='empty-result-message']"); const findEmptySearchMessage = () => wrapper.find("[data-testid='empty-result-message']");
const createWrapper = (state = {}) => { const createStore = ({ state, activeGroupProjects }) => {
const store = createStore({ Vue.use(Vuex);
groupProjects: [],
groupProjectsFlags: { store = new Vuex.Store({
isLoading: false, state: {
pageInfo: { defaultState,
hasNextPage: false, groupProjectsFlags: {
isLoading: false,
pageInfo: {
hasNextPage: false,
},
}, },
...state,
},
actions: {
fetchGroupProjects: jest.fn(),
setSelectedProject: jest.fn(),
}, },
...state, getters: {
activeGroupProjects: () => activeGroupProjects,
},
});
};
const createWrapper = ({ state = {}, activeGroupProjects = [] } = {}) => {
createStore({
state,
activeGroupProjects,
}); });
wrapper = mount(ProjectSelect, { wrapper = mount(ProjectSelect, {
localVue,
propsData: { propsData: {
list: mockList, list: mockList,
}, },
...@@ -93,7 +97,7 @@ describe('ProjectSelect component', () => { ...@@ -93,7 +97,7 @@ describe('ProjectSelect component', () => {
describe('when dropdown menu is open', () => { describe('when dropdown menu is open', () => {
describe('by default', () => { describe('by default', () => {
beforeEach(() => { beforeEach(() => {
createWrapper({ groupProjects: mockGroupProjects }); createWrapper({ activeGroupProjects: mockActiveGroupProjects });
}); });
it('shows GlSearchBoxByType with default attributes', () => { it('shows GlSearchBoxByType with default attributes', () => {
...@@ -128,7 +132,7 @@ describe('ProjectSelect component', () => { ...@@ -128,7 +132,7 @@ describe('ProjectSelect component', () => {
describe('when a project is selected', () => { describe('when a project is selected', () => {
beforeEach(() => { beforeEach(() => {
createWrapper({ groupProjects: mockProjectsList1 }); createWrapper({ activeGroupProjects: mockProjectsList1 });
findFirstGlDropdownItem().find('button').trigger('click'); findFirstGlDropdownItem().find('button').trigger('click');
}); });
...@@ -142,7 +146,7 @@ describe('ProjectSelect component', () => { ...@@ -142,7 +146,7 @@ describe('ProjectSelect component', () => {
describe('when projects are loading', () => { describe('when projects are loading', () => {
beforeEach(() => { beforeEach(() => {
createWrapper({ groupProjectsFlags: { isLoading: true } }); createWrapper({ state: { groupProjectsFlags: { isLoading: true } } });
}); });
it('displays and hides gl-loading-icon while and after fetching data', () => { it('displays and hides gl-loading-icon while and after fetching data', () => {
......
...@@ -7,6 +7,8 @@ import { ...@@ -7,6 +7,8 @@ import {
mockIssuesByListId, mockIssuesByListId,
issues, issues,
mockLists, mockLists,
mockGroupProject1,
mockArchivedGroupProject,
} from '../mock_data'; } from '../mock_data';
describe('Boards - Getters', () => { describe('Boards - Getters', () => {
...@@ -165,4 +167,14 @@ describe('Boards - Getters', () => { ...@@ -165,4 +167,14 @@ describe('Boards - Getters', () => {
expect(getters.getListByTitle(boardsState)('To Do')).toEqual(mockLists[1]); expect(getters.getListByTitle(boardsState)('To Do')).toEqual(mockLists[1]);
}); });
}); });
describe('activeGroupProjects', () => {
const state = {
groupProjects: [mockGroupProject1, mockArchivedGroupProject],
};
it('returns only returns non-archived group projects', () => {
expect(getters.activeGroupProjects(state)).toEqual([mockGroupProject1]);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment