web/satellite: project members frontend selection caching added (#3238)
This commit is contained in:
parent
f1867a954b
commit
875c7dfe72
@ -35,9 +35,10 @@
|
|||||||
is-white="true"
|
is-white="true"
|
||||||
:on-press="onClearSelection"
|
:on-press="onClearSelection"
|
||||||
/>
|
/>
|
||||||
|
<span class="header-selected-members__info-text"><b>{{selectedProjectMembersCount}}</b> users selected</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-after-delete-click" v-if="areSelectedProjectMembersBeingDeleted">
|
<div class="header-after-delete-click" v-if="areSelectedProjectMembersBeingDeleted">
|
||||||
<span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete {{selectedProjectMembersCount}} {{userCountTitle}}?</span>
|
<span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete <b>{{selectedProjectMembersCount}}</b> {{userCountTitle}}?</span>
|
||||||
<div class="header-after-delete-click__button-area">
|
<div class="header-after-delete-click__button-area">
|
||||||
<VButton
|
<VButton
|
||||||
class="button deletion"
|
class="button deletion"
|
||||||
@ -71,7 +72,7 @@ import VButton from '@/components/common/VButton.vue';
|
|||||||
import VHeader from '@/components/common/VHeader.vue';
|
import VHeader from '@/components/common/VHeader.vue';
|
||||||
import AddUserPopup from '@/components/team/AddUserPopup.vue';
|
import AddUserPopup from '@/components/team/AddUserPopup.vue';
|
||||||
|
|
||||||
import { ProjectMember, ProjectMemberHeaderState } from '@/types/projectMembers';
|
import { ProjectMemberHeaderState } from '@/types/projectMembers';
|
||||||
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
|
import { APP_STATE_ACTIONS, NOTIFICATION_ACTIONS, PM_ACTIONS } from '@/utils/constants/actionNames';
|
||||||
|
|
||||||
declare interface ClearSearch {
|
declare interface ClearSearch {
|
||||||
@ -119,22 +120,20 @@ export default class HeaderArea extends Vue {
|
|||||||
this.$store.dispatch(PM_ACTIONS.CLEAR_SELECTION);
|
this.$store.dispatch(PM_ACTIONS.CLEAR_SELECTION);
|
||||||
this.isDeleteClicked = false;
|
this.isDeleteClicked = false;
|
||||||
|
|
||||||
|
this.$emit('onSuccessAction');
|
||||||
this.$refs.headerComponent.clearSearch();
|
this.$refs.headerComponent.clearSearch();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async onDelete(): Promise<void> {
|
public async onDelete(): Promise<void> {
|
||||||
const projectMemberEmails: string[] = this.$store.getters.selectedProjectMembers.map((member: ProjectMember) => {
|
|
||||||
return member.user.email;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch(PM_ACTIONS.DELETE, projectMemberEmails);
|
await this.$store.dispatch(PM_ACTIONS.DELETE);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Error while deleting users from projectMembers. ${error.message}`);
|
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Error while deleting users from projectMembers. ${error.message}`);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$emit('onSuccessAction');
|
||||||
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Members was successfully removed from project');
|
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, 'Members was successfully removed from project');
|
||||||
this.isDeleteClicked = false;
|
this.isDeleteClicked = false;
|
||||||
|
|
||||||
@ -212,6 +211,11 @@ export default class HeaderArea extends Vue {
|
|||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
height: 85px;
|
height: 85px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
&__info-text {
|
||||||
|
margin-left: 25px;
|
||||||
|
line-height: 48px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
<div class="team-area__header">
|
<div class="team-area__header">
|
||||||
<HeaderArea
|
<HeaderArea
|
||||||
:header-state="headerState"
|
:header-state="headerState"
|
||||||
:selected-project-members-count="selectedProjectMembers.length"
|
:selected-project-members-count="selectedProjectMembersLength"
|
||||||
|
@onSuccessAction="resetPaginator"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="team-area__container" id="team-container" v-if="isTeamAreaShown">
|
<div class="team-area__container" id="team-container" v-if="isTeamAreaShown">
|
||||||
@ -99,7 +100,7 @@ export default class ProjectMembersArea extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onMemberClick(member: ProjectMember): void {
|
public onMemberClick(member: ProjectMember): void {
|
||||||
this.$store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, member.user.id);
|
this.$store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, member);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get projectMembers(): ProjectMember[] {
|
public get projectMembers(): ProjectMember[] {
|
||||||
@ -122,12 +123,12 @@ export default class ProjectMembersArea extends Vue {
|
|||||||
return this.$store.state.projectMembersModule.page.pageCount;
|
return this.$store.state.projectMembersModule.page.pageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get selectedProjectMembers(): ProjectMember[] {
|
public get selectedProjectMembersLength(): number {
|
||||||
return this.$store.getters.selectedProjectMembers;
|
return this.$store.state.projectMembersModule.selectedProjectMembersEmails.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get headerState(): number {
|
public get headerState(): number {
|
||||||
if (this.selectedProjectMembers.length > 0) {
|
if (this.selectedProjectMembersLength > 0) {
|
||||||
return ProjectMemberHeaderState.ON_SELECT;
|
return ProjectMemberHeaderState.ON_SELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +160,10 @@ export default class ProjectMembersArea extends Vue {
|
|||||||
await this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${error.message}`);
|
await this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Unable to fetch project members. ${error.message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.resetPaginator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public resetPaginator(): void {
|
||||||
if (this.totalPageCount > 1) {
|
if (this.totalPageCount > 1) {
|
||||||
this.$refs.pagination.resetPageIndex();
|
this.$refs.pagination.resetPageIndex();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ const {
|
|||||||
class ProjectMembersState {
|
class ProjectMembersState {
|
||||||
public cursor: ProjectMemberCursor = new ProjectMemberCursor();
|
public cursor: ProjectMemberCursor = new ProjectMemberCursor();
|
||||||
public page: ProjectMembersPage = new ProjectMembersPage();
|
public page: ProjectMembersPage = new ProjectMembersPage();
|
||||||
|
public selectedProjectMembersEmails: string[] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeProjectMembersModule(api: ProjectMembersApi): StoreModule<ProjectMembersState> {
|
export function makeProjectMembersModule(api: ProjectMembersApi): StoreModule<ProjectMembersState> {
|
||||||
@ -44,6 +45,13 @@ export function makeProjectMembersModule(api: ProjectMembersApi): StoreModule<Pr
|
|||||||
mutations: {
|
mutations: {
|
||||||
[FETCH](state: ProjectMembersState, page: ProjectMembersPage) {
|
[FETCH](state: ProjectMembersState, page: ProjectMembersPage) {
|
||||||
state.page = page;
|
state.page = page;
|
||||||
|
state.page.projectMembers = state.page.projectMembers.map(member => {
|
||||||
|
if (state.selectedProjectMembersEmails.includes(member.user.email)) {
|
||||||
|
member.isSelected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return member;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[SET_PAGE](state: ProjectMembersState, page: number) {
|
[SET_PAGE](state: ProjectMembersState, page: number) {
|
||||||
state.cursor.page = page;
|
state.cursor.page = page;
|
||||||
@ -60,17 +68,23 @@ export function makeProjectMembersModule(api: ProjectMembersApi): StoreModule<Pr
|
|||||||
[CLEAR](state: ProjectMembersState) {
|
[CLEAR](state: ProjectMembersState) {
|
||||||
state.cursor = new ProjectMemberCursor();
|
state.cursor = new ProjectMemberCursor();
|
||||||
state.page = new ProjectMembersPage();
|
state.page = new ProjectMembersPage();
|
||||||
|
state.selectedProjectMembersEmails = [];
|
||||||
},
|
},
|
||||||
[TOGGLE_SELECTION](state: ProjectMembersState, projectMemberId: string) {
|
[TOGGLE_SELECTION](state: ProjectMembersState, projectMember: ProjectMember) {
|
||||||
state.page.projectMembers = state.page.projectMembers.map((projectMember: ProjectMember) => {
|
if (!state.selectedProjectMembersEmails.includes(projectMember.user.email)) {
|
||||||
if (projectMember.user.id === projectMemberId) {
|
projectMember.isSelected = true;
|
||||||
projectMember.isSelected = !projectMember.isSelected;
|
state.selectedProjectMembersEmails.push(projectMember.user.email);
|
||||||
}
|
|
||||||
|
|
||||||
return projectMember;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
projectMember.isSelected = false;
|
||||||
|
state.selectedProjectMembersEmails = state.selectedProjectMembersEmails.filter(projectMemberEmail => {
|
||||||
|
return projectMemberEmail !== projectMember.user.email;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[CLEAR_SELECTION](state: ProjectMembersState) {
|
[CLEAR_SELECTION](state: ProjectMembersState) {
|
||||||
|
state.selectedProjectMembersEmails = [];
|
||||||
state.page.projectMembers = state.page.projectMembers.map((projectMember: ProjectMember) => {
|
state.page.projectMembers = state.page.projectMembers.map((projectMember: ProjectMember) => {
|
||||||
projectMember.isSelected = false;
|
projectMember.isSelected = false;
|
||||||
|
|
||||||
@ -84,10 +98,12 @@ export function makeProjectMembersModule(api: ProjectMembersApi): StoreModule<Pr
|
|||||||
|
|
||||||
await api.add(projectId, emails);
|
await api.add(projectId, emails);
|
||||||
},
|
},
|
||||||
deleteProjectMembers: async function ({rootGetters}: any, projectMemberEmails: string[]): Promise<void> {
|
deleteProjectMembers: async function ({rootGetters, state, commit}: any): Promise<void> {
|
||||||
const projectId = rootGetters.selectedProject.id;
|
const projectId = rootGetters.selectedProject.id;
|
||||||
|
|
||||||
await api.delete(projectId, projectMemberEmails);
|
await api.delete(projectId, state.selectedProjectMembersEmails);
|
||||||
|
|
||||||
|
commit(CLEAR_SELECTION);
|
||||||
},
|
},
|
||||||
fetchProjectMembers: async function ({commit, rootGetters, state}: any, page: number): Promise<ProjectMembersPage> {
|
fetchProjectMembers: async function ({commit, rootGetters, state}: any, page: number): Promise<ProjectMembersPage> {
|
||||||
const projectID = rootGetters.selectedProject.id;
|
const projectID = rootGetters.selectedProject.id;
|
||||||
@ -112,15 +128,17 @@ export function makeProjectMembersModule(api: ProjectMembersApi): StoreModule<Pr
|
|||||||
clearProjectMembers: function ({commit}) {
|
clearProjectMembers: function ({commit}) {
|
||||||
commit(CLEAR);
|
commit(CLEAR);
|
||||||
},
|
},
|
||||||
toggleProjectMemberSelection: function ({commit}: any, projectMemberId: string) {
|
toggleProjectMemberSelection: function ({commit}: any, projectMember: ProjectMember) {
|
||||||
commit(TOGGLE_SELECTION, projectMemberId);
|
commit(TOGGLE_SELECTION, projectMember);
|
||||||
},
|
},
|
||||||
clearProjectMemberSelection: function ({commit}: any) {
|
clearProjectMemberSelection: function ({commit}: any) {
|
||||||
commit(CLEAR_SELECTION);
|
commit(CLEAR_SELECTION);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
selectedProjectMembers: (state: any) => state.page.projectMembers.filter((member: ProjectMember) => member.isSelected),
|
selectedProjectMembers: (state: ProjectMembersState) =>
|
||||||
|
state.page.projectMembers.filter((member: ProjectMember) =>
|
||||||
|
state.selectedProjectMembersEmails.includes(member.user.email)),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,8 @@ export class ProjectMember {
|
|||||||
public joinedAt: string;
|
public joinedAt: string;
|
||||||
public isSelected: boolean;
|
public isSelected: boolean;
|
||||||
|
|
||||||
public constructor(fullName: string, shortName: string, email: string, joinedAt: string, id?: string) {
|
public constructor(fullName: string, shortName: string, email: string, joinedAt: string, id: string = '') {
|
||||||
this.user = new User(id || '', fullName, shortName, email);
|
this.user = new User(id, fullName, shortName, email);
|
||||||
this.joinedAt = joinedAt;
|
this.joinedAt = joinedAt;
|
||||||
this.isSelected = false;
|
this.isSelected = false;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ exports[`Team HeaderArea renders correctly with 1 selected user and delete click
|
|||||||
<vheader-stub placeholder="Team Members" search="function () { [native code] }">
|
<vheader-stub placeholder="Team Members" search="function () { [native code] }">
|
||||||
<!---->
|
<!---->
|
||||||
<!---->
|
<!---->
|
||||||
<div class="header-after-delete-click"><span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete 1 user?</span>
|
<div class="header-after-delete-click"><span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete <b>1</b> user?</span>
|
||||||
<div class="header-after-delete-click__button-area">
|
<div class="header-after-delete-click__button-area">
|
||||||
<vbutton-stub label="Delete" width="122px" height="48px" onpress="function () { [native code] }" class="button deletion"></vbutton-stub>
|
<vbutton-stub label="Delete" width="122px" height="48px" onpress="function () { [native code] }" class="button deletion"></vbutton-stub>
|
||||||
<vbutton-stub label="Cancel" width="122px" height="48px" iswhite="true" onpress="function () { [native code] }" class="button"></vbutton-stub>
|
<vbutton-stub label="Cancel" width="122px" height="48px" iswhite="true" onpress="function () { [native code] }" class="button"></vbutton-stub>
|
||||||
@ -46,7 +46,7 @@ exports[`Team HeaderArea renders correctly with 2 selected users and delete clic
|
|||||||
<vheader-stub placeholder="Team Members" search="function () { [native code] }">
|
<vheader-stub placeholder="Team Members" search="function () { [native code] }">
|
||||||
<!---->
|
<!---->
|
||||||
<!---->
|
<!---->
|
||||||
<div class="header-after-delete-click"><span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete 2 users?</span>
|
<div class="header-after-delete-click"><span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete <b>2</b> users?</span>
|
||||||
<div class="header-after-delete-click__button-area">
|
<div class="header-after-delete-click__button-area">
|
||||||
<vbutton-stub label="Delete" width="122px" height="48px" onpress="function () { [native code] }" class="button deletion"></vbutton-stub>
|
<vbutton-stub label="Delete" width="122px" height="48px" onpress="function () { [native code] }" class="button deletion"></vbutton-stub>
|
||||||
<vbutton-stub label="Cancel" width="122px" height="48px" iswhite="true" onpress="function () { [native code] }" class="button"></vbutton-stub>
|
<vbutton-stub label="Cancel" width="122px" height="48px" iswhite="true" onpress="function () { [native code] }" class="button"></vbutton-stub>
|
||||||
@ -86,7 +86,7 @@ exports[`Team HeaderArea renders correctly with selected users 1`] = `
|
|||||||
<!---->
|
<!---->
|
||||||
<div class="header-selected-members">
|
<div class="header-selected-members">
|
||||||
<vbutton-stub label="Delete" width="122px" height="48px" onpress="function () { [native code] }" class="button deletion"></vbutton-stub>
|
<vbutton-stub label="Delete" width="122px" height="48px" onpress="function () { [native code] }" class="button deletion"></vbutton-stub>
|
||||||
<vbutton-stub label="Cancel" width="122px" height="48px" iswhite="true" onpress="function () { [native code] }" class="button"></vbutton-stub>
|
<vbutton-stub label="Cancel" width="122px" height="48px" iswhite="true" onpress="function () { [native code] }" class="button"></vbutton-stub> <span class="header-selected-members__info-text"><b>2</b> users selected</span>
|
||||||
</div>
|
</div>
|
||||||
<!---->
|
<!---->
|
||||||
</vheader-stub>
|
</vheader-stub>
|
||||||
|
@ -79,9 +79,24 @@ describe('mutations', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('toggle selection', function () {
|
it('toggle selection', function () {
|
||||||
store.commit(PROJECT_MEMBER_MUTATIONS.TOGGLE_SELECTION, projectMember1.user.id);
|
const testProjectMembersPage = new ProjectMembersPage();
|
||||||
|
testProjectMembersPage.projectMembers = [projectMember1];
|
||||||
|
testProjectMembersPage.totalCount = 1;
|
||||||
|
testProjectMembersPage.pageCount = 1;
|
||||||
|
|
||||||
|
store.commit(PROJECT_MEMBER_MUTATIONS.TOGGLE_SELECTION, projectMember1);
|
||||||
|
|
||||||
expect(state.page.projectMembers[0].isSelected).toBe(true);
|
expect(state.page.projectMembers[0].isSelected).toBe(true);
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(1);
|
||||||
|
|
||||||
|
store.commit(PROJECT_MEMBER_MUTATIONS.FETCH, testProjectMembersPage);
|
||||||
|
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(1);
|
||||||
|
|
||||||
|
store.commit(PROJECT_MEMBER_MUTATIONS.TOGGLE_SELECTION, projectMember1);
|
||||||
|
|
||||||
|
expect(state.page.projectMembers[0].isSelected).toBe(false);
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clear selection', function () {
|
it('clear selection', function () {
|
||||||
@ -90,6 +105,8 @@ describe('mutations', () => {
|
|||||||
state.page.projectMembers.forEach((pm: ProjectMember) => {
|
state.page.projectMembers.forEach((pm: ProjectMember) => {
|
||||||
expect(pm.isSelected).toBe(false);
|
expect(pm.isSelected).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clear store', function () {
|
it('clear store', function () {
|
||||||
@ -100,6 +117,7 @@ describe('mutations', () => {
|
|||||||
expect(state.cursor.order).toBe(ProjectMemberOrderBy.NAME);
|
expect(state.cursor.order).toBe(ProjectMemberOrderBy.NAME);
|
||||||
expect(state.cursor.orderDirection).toBe(SortDirection.ASCENDING);
|
expect(state.cursor.orderDirection).toBe(SortDirection.ASCENDING);
|
||||||
expect(state.page.projectMembers.length).toBe(0);
|
expect(state.page.projectMembers.length).toBe(0);
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -243,9 +261,25 @@ describe('actions', async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await store.dispatch(PM_ACTIONS.FETCH, FIRST_PAGE);
|
await store.dispatch(PM_ACTIONS.FETCH, FIRST_PAGE);
|
||||||
store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, projectMember1.user.id);
|
store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, projectMember1);
|
||||||
|
|
||||||
expect(state.page.projectMembers[0].isSelected).toBe(true);
|
expect(state.page.projectMembers[0].isSelected).toBe(true);
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(1);
|
||||||
|
|
||||||
|
store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, projectMember2);
|
||||||
|
|
||||||
|
expect(state.page.projectMembers[1].isSelected).toBe(true);
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(2);
|
||||||
|
|
||||||
|
await store.dispatch(PM_ACTIONS.FETCH, FIRST_PAGE);
|
||||||
|
|
||||||
|
expect(state.page.projectMembers[1].isSelected).toBe(true);
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(2);
|
||||||
|
|
||||||
|
store.dispatch(PM_ACTIONS.TOGGLE_SELECTION, projectMember1);
|
||||||
|
|
||||||
|
expect(state.page.projectMembers[0].isSelected).toBe(false);
|
||||||
|
expect(state.selectedProjectMembersEmails.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clear selection', function () {
|
it('clear selection', function () {
|
||||||
@ -269,7 +303,6 @@ describe('actions', async () => {
|
|||||||
|
|
||||||
describe('getters', () => {
|
describe('getters', () => {
|
||||||
const selectedProjectMember = new ProjectMember('testFullName2', 'testShortName2', 'test2@example.com', 'now2', '2');
|
const selectedProjectMember = new ProjectMember('testFullName2', 'testShortName2', 'test2@example.com', 'now2', '2');
|
||||||
selectedProjectMember.isSelected = true;
|
|
||||||
|
|
||||||
it('selected project members', function () {
|
it('selected project members', function () {
|
||||||
const testProjectMembersPage = new ProjectMembersPage();
|
const testProjectMembersPage = new ProjectMembersPage();
|
||||||
@ -278,6 +311,7 @@ describe('getters', () => {
|
|||||||
testProjectMembersPage.pageCount = 1;
|
testProjectMembersPage.pageCount = 1;
|
||||||
|
|
||||||
store.commit(PROJECT_MEMBER_MUTATIONS.FETCH, testProjectMembersPage);
|
store.commit(PROJECT_MEMBER_MUTATIONS.FETCH, testProjectMembersPage);
|
||||||
|
store.commit(PROJECT_MEMBER_MUTATIONS.TOGGLE_SELECTION, selectedProjectMember);
|
||||||
|
|
||||||
const retrievedProjectMembers = store.getters.selectedProjectMembers;
|
const retrievedProjectMembers = store.getters.selectedProjectMembers;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user