From 15a6b35485bdcfe3bc57f1328a622c40b6faa660 Mon Sep 17 00:00:00 2001 From: rgermain Date: Wed, 18 Feb 2026 10:52:02 +0100 Subject: [PATCH 01/12] refactor(group): refactor group modules --- src/api/crisalid.service.ts | 66 +++ src/api/groups.service.ts | 115 +++-- src/api/v2/crisalid.service.ts | 152 +++++++ src/api/v2/group.service.ts | 146 ++++++ .../group/Modules/BaseGroupPreview.vue | 88 ++++ .../Documents/GroupDocumentsPreview.vue | 43 ++ .../Extras/GroupDescriptionPreview.vue | 18 + .../Modules/Extras/GroupRecapPreview.vue | 97 ++++ .../Modules/Extras/GroupSimilarDrawer.vue | 69 +++ .../Modules/Extras/GroupSimilarsPreview.vue | 115 +++++ src/components/group/Modules/GroupHeader.vue | 229 ++++++++++ .../group/Modules/GroupSub/GroupSubDrawer.vue | 29 ++ .../group/Modules/GroupSub/GroupSubList.vue | 57 +++ .../Modules/GroupSub/GroupSubPreview.vue | 34 ++ .../Modules/GroupSub/GroupSubTeamItem.vue | 88 ++++ .../Modules/Members/BaseGroupMembersList.vue | 85 ++++ .../group/Modules/Members/GroupMemberItem.vue | 131 ++++++ .../Modules/Members/GroupMembersPreview.vue | 40 ++ .../Projects/BaseGroupProjectsList.vue | 36 ++ .../Modules/Projects/GroupProjectsPreview.vue | 34 ++ .../home/HomeButtons/HomeButtons.vue | 2 +- .../GroupResearcherDocumentsList.vue | 269 +++++++++++ .../Researcher/OwnResearcherDocumentsList.vue | 261 +++++++++++ .../ResearcherDocumentsListBase.vue | 400 +++++++++++++++++ .../ProjectMemberSection.vue | 112 +++++ src/components/project/ProjectPreview.vue | 114 +++++ src/pages/GroupPageV2/Tabs/BaseGroupTab.vue | 55 +++ .../Tabs/Documents/GroupDocumentsTab.vue | 20 + src/pages/GroupPageV2/Tabs/GroupEditTab.vue | 425 ++++++++++++++++++ .../Tabs/Members/GroupMembersEditTab.vue | 62 +++ .../Tabs/Members/GroupMembersTab.vue | 30 ++ .../Tabs/Projects/GroupProjectsEditTab.vue | 59 +++ .../Tabs/Projects/GroupProjectsTab.vue | 18 + src/skeletons/base.skeletons.ts | 22 + src/skeletons/crisalid.skeletons.ts | 46 ++ src/skeletons/group.skeletons.ts | 50 +++ src/skeletons/project.skeletons.ts | 44 ++ 37 files changed, 3615 insertions(+), 46 deletions(-) create mode 100644 src/api/crisalid.service.ts create mode 100644 src/api/v2/crisalid.service.ts create mode 100644 src/api/v2/group.service.ts create mode 100644 src/components/group/Modules/BaseGroupPreview.vue create mode 100644 src/components/group/Modules/Documents/GroupDocumentsPreview.vue create mode 100644 src/components/group/Modules/Extras/GroupDescriptionPreview.vue create mode 100644 src/components/group/Modules/Extras/GroupRecapPreview.vue create mode 100644 src/components/group/Modules/Extras/GroupSimilarDrawer.vue create mode 100644 src/components/group/Modules/Extras/GroupSimilarsPreview.vue create mode 100644 src/components/group/Modules/GroupHeader.vue create mode 100644 src/components/group/Modules/GroupSub/GroupSubDrawer.vue create mode 100644 src/components/group/Modules/GroupSub/GroupSubList.vue create mode 100644 src/components/group/Modules/GroupSub/GroupSubPreview.vue create mode 100644 src/components/group/Modules/GroupSub/GroupSubTeamItem.vue create mode 100644 src/components/group/Modules/Members/BaseGroupMembersList.vue create mode 100644 src/components/group/Modules/Members/GroupMemberItem.vue create mode 100644 src/components/group/Modules/Members/GroupMembersPreview.vue create mode 100644 src/components/group/Modules/Projects/BaseGroupProjectsList.vue create mode 100644 src/components/group/Modules/Projects/GroupProjectsPreview.vue create mode 100644 src/components/people/Researcher/GroupResearcherDocumentsList.vue create mode 100644 src/components/people/Researcher/OwnResearcherDocumentsList.vue create mode 100644 src/components/people/Researcher/ResearcherDocumentsListBase.vue create mode 100644 src/components/project/ProjectMemberSection/ProjectMemberSection.vue create mode 100644 src/components/project/ProjectPreview.vue create mode 100644 src/pages/GroupPageV2/Tabs/BaseGroupTab.vue create mode 100644 src/pages/GroupPageV2/Tabs/Documents/GroupDocumentsTab.vue create mode 100644 src/pages/GroupPageV2/Tabs/GroupEditTab.vue create mode 100644 src/pages/GroupPageV2/Tabs/Members/GroupMembersEditTab.vue create mode 100644 src/pages/GroupPageV2/Tabs/Members/GroupMembersTab.vue create mode 100644 src/pages/GroupPageV2/Tabs/Projects/GroupProjectsEditTab.vue create mode 100644 src/pages/GroupPageV2/Tabs/Projects/GroupProjectsTab.vue create mode 100644 src/skeletons/base.skeletons.ts create mode 100644 src/skeletons/crisalid.skeletons.ts create mode 100644 src/skeletons/group.skeletons.ts create mode 100644 src/skeletons/project.skeletons.ts diff --git a/src/api/crisalid.service.ts b/src/api/crisalid.service.ts new file mode 100644 index 000000000..b14a013e1 --- /dev/null +++ b/src/api/crisalid.service.ts @@ -0,0 +1,66 @@ +import { + Document, + DocumentType, + Researcher, + ResearcherDocumentAnalytics, +} from '@/interfaces/researcher' +import { PeopleGroupModel } from '@/models/invitation.model' + +export async function getOwnResearchDocument( + organisationCode: string, + researchId: Researcher['id'], + documentType: DocumentType, + config = {} +) { + return await useAPI>( + `crisalid/organization/${organisationCode}/researcher/${researchId}/${documentType}/`, + config + ) +} + +export async function getGroupResearchDocument( + organisationCode: string, + groupId: PeopleGroupModel['id'], + documentType: DocumentType, + config = {} +) { + return await useAPI>( + `crisalid/organization/${organisationCode}/people-group/${groupId}/${documentType}/`, + config + ) +} + +export async function getOwnResearchDocumentAnalytics( + organisationCode: string, + researchId: Researcher['id'], + documentType: DocumentType, + config = {} +) { + return await useAPI( + `crisalid/organization/${organisationCode}/researcher/${researchId}/${documentType}/analytics/`, + config + ) +} + +export async function getGroupResearchDocumentAnalytics( + organisationCode: string, + groupId: PeopleGroupModel['id'], + documentType: DocumentType, + config = {} +) { + return await useAPI( + `crisalid/organization/${organisationCode}/people-group/${groupId}/${documentType}/analytics/`, + config + ) +} + +export async function getResearchDocumentSimilars( + organisationCode: string, + documentId: Document['id'], + config = {} +) { + return await useAPI>( + `crisalid/organization/${organisationCode}/document/${documentId}/similars/`, + config + ) +} diff --git a/src/api/groups.service.ts b/src/api/groups.service.ts index 2f75e1604..3164d5830 100644 --- a/src/api/groups.service.ts +++ b/src/api/groups.service.ts @@ -1,31 +1,33 @@ import type { - // GroupModel, - // GroupOuput, PostGroupData, AddGroupMembers, RemoveGroupMember, PostGroupProjects, AddParentGroupModelInput, + GroupMember, + HierarchyGroupModel, } from '@/models/group.model' -// import type { HierarchyGroupModel } from '@/models/group.model' -// import type { APIResponseList } from '@/api/types' import { _adaptParamsToGetQuery } from '@/api/utils.service' import useAPI from '@/composables/useAPI' +import { ProjectModel } from '@/models/project.model' +import { PeopleGroupModel } from '@/models/invitation.model' // HIERARCHY - -export async function getHierarchyGroups(org: string) { - return await useAPI(`organization/${org}/people-groups-hierarchy/`, {}) //.data.value +export async function getHierarchyGroups(organizationCode: string, config = {}) { + return await useAPI>( + `organization/${organizationCode}/people-groups-hierarchy/`, + config + ) } export async function getPeopleGroupsHierarchy(org_code, params) { return await useAPI(`organization/${org_code}/people-groups-hierarchy/`, { ..._adaptParamsToGetQuery(params), - }) //.data.value + }) } export async function getGroups(org_id) { - return await useAPI(`organization/${org_id}/people-group/`, {}) //.data.value + return await useAPI(`organization/${org_id}/people-group/`, {}) } // ALL GROUPS @@ -33,80 +35,85 @@ export async function getGroups(org_id) { export async function getPeopleGroups(org_code, params) { return await useAPI(`organization/${org_code}/people-group/`, { ..._adaptParamsToGetQuery(params), - }) //.data.value + }) } export async function postGroup(org: string, groupData: PostGroupData) { return await useAPI(`organization/${org}/people-group/`, { body: groupData, method: 'POST' }) - //.data.value } // GROUP export async function addParentGroup( orgId: string, - groupId: string, + groupId: number, body: AddParentGroupModelInput ) { - return await useAPI(`organization/${orgId}/people-group/${groupId}/`, { body, method: 'PATCH' }) //.data.value + return await useAPI(`organization/${orgId}/people-group/${groupId}/`, { body, method: 'PATCH' }) } -export async function getGroup(org: string, groupId: string, noError: boolean = false) { - return await useAPI( - `/organization/${org}/people-group/${groupId}/`, - { noError: noError } // TODO nuxt check error silenced - ) //.data.value +export function getGroup(organizationCode: string, groupId: number, config = {}) { + return useAPI( + `organization/${organizationCode}/people-group/${groupId}/`, + config + ) } -export async function patchGroup(org: string, group_id: number, groupData: Partial) { - return await useAPI(`organization/${org}/people-group/${group_id}/`, { +export async function patchGroup( + organizationCode: string, + groupName: number, + groupData: Partial +) { + return await useAPI(`organization/${organizationCode}/people-group/${groupName}/`, { body: groupData, method: 'PATCH', - }) //.data.value + }) } -export async function deleteGroup(org_code, group_id) { - return await useAPI(`organization/${org_code}/people-group/${group_id}/`, { method: 'DELETE' }) //.data.value +export async function deleteGroup(organizationCode: string, groupName: string) { + return await useAPI(`organization/${organizationCode}/people-group/${groupName}/`, { + method: 'DELETE', + }) } // GROUP MEMBERS -export async function getGroupMember(org: string, groupId: string, noError: boolean = false) { - return ( - // TODO nuxt check error silenced - await useAPI(`organization/${org}/people-group/${groupId}/member/`, { noError: noError }) - //.data.value +export async function getGroupMember(organizationCode: string, groupId: number, config = {}) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/member/`, + config ) } export async function postGroupMembers( - org: string, - group_id: number, + organizationCode: string, + groupId: number, membersData: AddGroupMembers ) { - return await useAPI(`organization/${org}/people-group/${group_id}/member/add/`, { + return await useAPI(`organization/${organizationCode}/people-group/${groupId}/member/add/`, { body: membersData, method: 'POST', - }) //.data.value + }) } export async function removeGroupMember( - org: string, - group_id: number, + organizationCode: string, + groupId: number, membersData: RemoveGroupMember ) { - return await useAPI(`organization/${org}/people-group/${group_id}/member/remove/`, { + return await useAPI(`organization/${organizationCode}/people-group/${groupId}/member/remove/`, { body: membersData, method: 'POST', - }) //.data.value + }) } // GROUP PROJECTS -export async function getGroupProject(org: string, groupId: string, noError: boolean = false) { - return await useAPI(`organization/${org}/people-group/${groupId}/project/`, { - noError: noError, - }) //.data.value +export async function getGroupProject(organizationCode: string, groupId: number, config = {}) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/project/`, + config + ) } export async function postGroupProjects( @@ -117,14 +124,18 @@ export async function postGroupProjects( return await useAPI(`organization/${org}/people-group/${group_id}/project/add/`, { body: projectsData, method: 'POST', - }) //.data.value + }) } -export async function removeGroupProject(org: string, group_id: number, projectsData: any) { +export async function removeGroupProject( + org: string, + group_id: number, + projectsData: PostGroupProjects +) { return await useAPI(`organization/${org}/people-group/${group_id}/project/remove/`, { body: projectsData, method: 'POST', - }) //.data.value + }) } // GROUP HEADER @@ -133,12 +144,26 @@ export async function postGroupHeader(org: string, group_id: number, headerData: return await useAPI(`organization/${org}/people-group/${group_id}/header/`, { body: headerData, method: 'POST', - }) //.data.value + }) } export async function patchGroupHeader(org: string, group_id: number, headerData: FormData) { return await useAPI(`organization/${org}/people-group/${group_id}/header/`, { body: headerData, method: 'PATCH', - }) //.data.value + }) +} + +export async function getGroupSimilar(organizationCode: string, groupId: number, config = {}) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/similars/`, + config + ) +} + +export async function getSubGroup(organizationCode: string, groupId: number, config = {}) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/subgroups/`, + config + ) } diff --git a/src/api/v2/crisalid.service.ts b/src/api/v2/crisalid.service.ts new file mode 100644 index 000000000..22e652244 --- /dev/null +++ b/src/api/v2/crisalid.service.ts @@ -0,0 +1,152 @@ +import { + getOwnResearchDocument as fetchOwnResearchDocument, + getGroupResearchDocument as fetchGroupResearchDocument, + getResearchDocumentSimilars as fetchResearchDocumentSimilars, + getOwnResearchDocumentAnalytics as fetchOwnResearchDocumentAnalytics, + getGroupResearchDocumentAnalytics as fetchGroupResearchDocumentAnalytics, +} from '@/api/crisalid.service' +import useAsyncAPI from '@/composables/useAsyncAPI' +import useAsyncPaginationAPI from '@/composables/useAsyncPaginationAPI' +import { onlyRefs } from '@/functs/onlyRefs' +import { Document, DocumentType, Researcher } from '@/interfaces/researcher' +import { RefOrRaw } from '@/interfaces/utils' +import { GroupModel } from '@/models/group.model' +import { PeopleGroupModel } from '@/models/invitation.model' +import { OrganizationModel } from '@/models/organization.model' + +const DEFAULT_CONFIG = {} + +export const getOwnResearchDocument = ( + organizationCode: RefOrRaw, + researcherId: RefOrRaw, + documenType: DocumentType, + config = {} +) => { + const { translateResearcherDocuments } = useAutoTranslate() + const key = computed( + () => `${unref(organizationCode)}::researcher::${unref(researcherId)}::${documenType}` + ) + + return useAsyncPaginationAPI( + key, + ({ config }) => + fetchOwnResearchDocument(unref(organizationCode), unref(researcherId), unref(documenType), { + ...DEFAULT_CONFIG, + ...config, + }), + { + translate: (data) => translateResearcherDocuments(data), + watch: onlyRefs([organizationCode, researcherId]), + ...config, + } + ) +} + +export const getGroupResearchDocument = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + documenType: DocumentType, + config = {} +) => { + const { translateResearcherDocuments } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::group::${unref(groupId)}::${documenType}`) + + return useAsyncPaginationAPI( + key, + ({ config }) => + fetchGroupResearchDocument(unref(organizationCode), unref(groupId), unref(documenType), { + ...DEFAULT_CONFIG, + ...config, + }), + { + translate: (data) => translateResearcherDocuments(data), + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} + +export const getOwnResearchDocumentAnalytics = ( + organizationCode: RefOrRaw, + researcherId: RefOrRaw, + documenType: DocumentType, + config = {} +) => { + const key = computed( + () => + `${unref(organizationCode)}::researcher::${unref(researcherId)}::${documenType}::analytics` + ) + + return useAsyncAPI( + key, + ({ config }) => + fetchOwnResearchDocumentAnalytics( + unref(organizationCode), + unref(researcherId), + unref(documenType), + { + ...DEFAULT_CONFIG, + ...config, + } + ), + { + watch: onlyRefs([organizationCode, researcherId]), + ...config, + } + ) +} + +export const getGroupResearchDocumentAnalytics = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + documenType: DocumentType, + config = {} +) => { + const key = computed( + () => `${unref(organizationCode)}::group::${unref(groupId)}::${documenType}::analytics` + ) + + return useAsyncAPI( + key, + ({ config }) => + fetchGroupResearchDocumentAnalytics( + unref(organizationCode), + unref(groupId), + unref(documenType), + { + ...DEFAULT_CONFIG, + ...config, + } + ), + { + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} + +export const getResearchDocumentSimilars = ( + organizationCode: RefOrRaw, + documentId: RefOrRaw, + config = {} +) => { + const { translateResearcherDocuments } = useAutoTranslate() + const key = computed( + () => `${unref(organizationCode)}::crisalid::document::${unref(documentId)}::similars` + ) + + return useAsyncPaginationAPI( + key, + ({ config }) => + fetchResearchDocumentSimilars(unref(organizationCode), unref(documentId), { + ...DEFAULT_CONFIG, + ...config, + }), + { + translate: (data) => translateResearcherDocuments(data), + watch: onlyRefs([organizationCode, documentId]), + checkArgs: true, + ...config, + } + ) +} diff --git a/src/api/v2/group.service.ts b/src/api/v2/group.service.ts new file mode 100644 index 000000000..d886ee847 --- /dev/null +++ b/src/api/v2/group.service.ts @@ -0,0 +1,146 @@ +import { + getGroup as fetchGetGroup, + getGroupProject as fetchGetGroupProject, + getHierarchyGroups as fetchGetHierarchyGroups, + getGroupMember as fetchGetGroupMember, + getGroupSimilar as fetchGetGroupSimilar, + getSubGroup as fetchGetSubGroup, + getGroupLocation as fetchLocationsGroup, + getGroupGallery as fetchGroupGallery, +} from '@/api/groups.service' +import useAsyncAPI from '@/composables/useAsyncAPI' +import useAsyncPaginationAPI from '@/composables/useAsyncPaginationAPI' +import { onlyRefs } from '@/functs/onlyRefs' +import { RefOrRaw } from '@/interfaces/utils' +import { GroupModel } from '@/models/group.model' +import { OrganizationModel } from '@/models/organization.model' + +const DEFAULT_CONFIG = {} + +export const getGroup = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + config = {} +) => { + const { translateGroup } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::group::${unref(groupId)}`) + + return useAsyncAPI( + key, + () => fetchGetGroup(unref(organizationCode), unref(groupId), { ...DEFAULT_CONFIG }), + { + translate: translateGroup, + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} + +export const getHierarchyGroups = ( + organizationCode: RefOrRaw, + config = {} +) => { + const { translateGroup } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::hierarchy-groups`) + + return useAsyncAPI( + key, + ({ config }) => + fetchGetHierarchyGroups(unref(organizationCode), { ...DEFAULT_CONFIG, ...config }), + { + translate: translateGroup, + watch: onlyRefs([organizationCode]), + ...config, + } + ) +} + +export const getGroupProject = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + config = {} +) => { + const { translateProjects } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::group::${unref(groupId)}::projects`) + + return useAsyncPaginationAPI( + key, + ({ config }) => + fetchGetGroupProject(unref(organizationCode), unref(groupId), { + ...DEFAULT_CONFIG, + ...config, + }), + { + translate: translateProjects, + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} + +export const getGroupMember = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + config = {} +) => { + const key = computed(() => `${unref(organizationCode)}::group::${unref(groupId)}::members`) + + return useAsyncPaginationAPI( + key, + ({ config }) => + fetchGetGroupMember(unref(organizationCode), unref(groupId), { + ...DEFAULT_CONFIG, + ...config, + }), + { + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} + +export const getGroupSimilar = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + config = {} +) => { + const { translateGroups } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::group::${unref(groupId)}::similars`) + + return useAsyncPaginationAPI( + key, + ({ config }) => + fetchGetGroupSimilar(unref(organizationCode), unref(groupId), { + ...DEFAULT_CONFIG, + ...config, + }), + { + translate: translateGroups, + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} + +export const getSubGroup = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + config = {} +) => { + const { translateGroups } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::group::${unref(groupId)}::subgroup`) + + return useAsyncPaginationAPI( + key, + ({ config }) => + fetchGetSubGroup(unref(organizationCode), unref(groupId), { + ...DEFAULT_CONFIG, + ...config, + }), + { + translate: translateGroups, + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} diff --git a/src/components/group/Modules/BaseGroupPreview.vue b/src/components/group/Modules/BaseGroupPreview.vue new file mode 100644 index 000000000..bb9157ce0 --- /dev/null +++ b/src/components/group/Modules/BaseGroupPreview.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/components/group/Modules/Documents/GroupDocumentsPreview.vue b/src/components/group/Modules/Documents/GroupDocumentsPreview.vue new file mode 100644 index 000000000..360c697e4 --- /dev/null +++ b/src/components/group/Modules/Documents/GroupDocumentsPreview.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/components/group/Modules/Extras/GroupDescriptionPreview.vue b/src/components/group/Modules/Extras/GroupDescriptionPreview.vue new file mode 100644 index 000000000..4e80a73d9 --- /dev/null +++ b/src/components/group/Modules/Extras/GroupDescriptionPreview.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/components/group/Modules/Extras/GroupRecapPreview.vue b/src/components/group/Modules/Extras/GroupRecapPreview.vue new file mode 100644 index 000000000..5f93f07f0 --- /dev/null +++ b/src/components/group/Modules/Extras/GroupRecapPreview.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/components/group/Modules/Extras/GroupSimilarDrawer.vue b/src/components/group/Modules/Extras/GroupSimilarDrawer.vue new file mode 100644 index 000000000..d988249c8 --- /dev/null +++ b/src/components/group/Modules/Extras/GroupSimilarDrawer.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/src/components/group/Modules/Extras/GroupSimilarsPreview.vue b/src/components/group/Modules/Extras/GroupSimilarsPreview.vue new file mode 100644 index 000000000..78886aca1 --- /dev/null +++ b/src/components/group/Modules/Extras/GroupSimilarsPreview.vue @@ -0,0 +1,115 @@ + + + + + + + diff --git a/src/components/group/Modules/GroupHeader.vue b/src/components/group/Modules/GroupHeader.vue new file mode 100644 index 000000000..01b5388a3 --- /dev/null +++ b/src/components/group/Modules/GroupHeader.vue @@ -0,0 +1,229 @@ + + + + + + + diff --git a/src/components/group/Modules/GroupSub/GroupSubDrawer.vue b/src/components/group/Modules/GroupSub/GroupSubDrawer.vue new file mode 100644 index 000000000..5437b6c46 --- /dev/null +++ b/src/components/group/Modules/GroupSub/GroupSubDrawer.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/group/Modules/GroupSub/GroupSubList.vue b/src/components/group/Modules/GroupSub/GroupSubList.vue new file mode 100644 index 000000000..903f3e597 --- /dev/null +++ b/src/components/group/Modules/GroupSub/GroupSubList.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/src/components/group/Modules/GroupSub/GroupSubPreview.vue b/src/components/group/Modules/GroupSub/GroupSubPreview.vue new file mode 100644 index 000000000..99a9d989d --- /dev/null +++ b/src/components/group/Modules/GroupSub/GroupSubPreview.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/components/group/Modules/GroupSub/GroupSubTeamItem.vue b/src/components/group/Modules/GroupSub/GroupSubTeamItem.vue new file mode 100644 index 000000000..1ec52e8a2 --- /dev/null +++ b/src/components/group/Modules/GroupSub/GroupSubTeamItem.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/src/components/group/Modules/Members/BaseGroupMembersList.vue b/src/components/group/Modules/Members/BaseGroupMembersList.vue new file mode 100644 index 000000000..231c28390 --- /dev/null +++ b/src/components/group/Modules/Members/BaseGroupMembersList.vue @@ -0,0 +1,85 @@ + + + + + + + diff --git a/src/components/group/Modules/Members/GroupMemberItem.vue b/src/components/group/Modules/Members/GroupMemberItem.vue new file mode 100644 index 000000000..f99e2dab3 --- /dev/null +++ b/src/components/group/Modules/Members/GroupMemberItem.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/src/components/group/Modules/Members/GroupMembersPreview.vue b/src/components/group/Modules/Members/GroupMembersPreview.vue new file mode 100644 index 000000000..ba0aa6595 --- /dev/null +++ b/src/components/group/Modules/Members/GroupMembersPreview.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/components/group/Modules/Projects/BaseGroupProjectsList.vue b/src/components/group/Modules/Projects/BaseGroupProjectsList.vue new file mode 100644 index 000000000..d301db62b --- /dev/null +++ b/src/components/group/Modules/Projects/BaseGroupProjectsList.vue @@ -0,0 +1,36 @@ + + + diff --git a/src/components/group/Modules/Projects/GroupProjectsPreview.vue b/src/components/group/Modules/Projects/GroupProjectsPreview.vue new file mode 100644 index 000000000..c1ccfe084 --- /dev/null +++ b/src/components/group/Modules/Projects/GroupProjectsPreview.vue @@ -0,0 +1,34 @@ + + + + + diff --git a/src/components/home/HomeButtons/HomeButtons.vue b/src/components/home/HomeButtons/HomeButtons.vue index f4bdfd7ff..a974e5d9d 100644 --- a/src/components/home/HomeButtons/HomeButtons.vue +++ b/src/components/home/HomeButtons/HomeButtons.vue @@ -1,5 +1,5 @@ + + + + diff --git a/src/components/people/Researcher/OwnResearcherDocumentsList.vue b/src/components/people/Researcher/OwnResearcherDocumentsList.vue new file mode 100644 index 000000000..9ac3f2f17 --- /dev/null +++ b/src/components/people/Researcher/OwnResearcherDocumentsList.vue @@ -0,0 +1,261 @@ + + + + + diff --git a/src/components/people/Researcher/ResearcherDocumentsListBase.vue b/src/components/people/Researcher/ResearcherDocumentsListBase.vue new file mode 100644 index 000000000..ad69ab34d --- /dev/null +++ b/src/components/people/Researcher/ResearcherDocumentsListBase.vue @@ -0,0 +1,400 @@ + + + + + diff --git a/src/components/project/ProjectMemberSection/ProjectMemberSection.vue b/src/components/project/ProjectMemberSection/ProjectMemberSection.vue new file mode 100644 index 000000000..54056a0e9 --- /dev/null +++ b/src/components/project/ProjectMemberSection/ProjectMemberSection.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/src/components/project/ProjectPreview.vue b/src/components/project/ProjectPreview.vue new file mode 100644 index 000000000..1cd6e3fa3 --- /dev/null +++ b/src/components/project/ProjectPreview.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/src/pages/GroupPageV2/Tabs/BaseGroupTab.vue b/src/pages/GroupPageV2/Tabs/BaseGroupTab.vue new file mode 100644 index 000000000..996d87df8 --- /dev/null +++ b/src/pages/GroupPageV2/Tabs/BaseGroupTab.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/pages/GroupPageV2/Tabs/Documents/GroupDocumentsTab.vue b/src/pages/GroupPageV2/Tabs/Documents/GroupDocumentsTab.vue new file mode 100644 index 000000000..f4a654cfd --- /dev/null +++ b/src/pages/GroupPageV2/Tabs/Documents/GroupDocumentsTab.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/pages/GroupPageV2/Tabs/GroupEditTab.vue b/src/pages/GroupPageV2/Tabs/GroupEditTab.vue new file mode 100644 index 000000000..0a2ecd4b4 --- /dev/null +++ b/src/pages/GroupPageV2/Tabs/GroupEditTab.vue @@ -0,0 +1,425 @@ + + + diff --git a/src/pages/GroupPageV2/Tabs/Members/GroupMembersEditTab.vue b/src/pages/GroupPageV2/Tabs/Members/GroupMembersEditTab.vue new file mode 100644 index 000000000..ebe571d86 --- /dev/null +++ b/src/pages/GroupPageV2/Tabs/Members/GroupMembersEditTab.vue @@ -0,0 +1,62 @@ + + + diff --git a/src/pages/GroupPageV2/Tabs/Members/GroupMembersTab.vue b/src/pages/GroupPageV2/Tabs/Members/GroupMembersTab.vue new file mode 100644 index 000000000..d904a81cf --- /dev/null +++ b/src/pages/GroupPageV2/Tabs/Members/GroupMembersTab.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/src/pages/GroupPageV2/Tabs/Projects/GroupProjectsEditTab.vue b/src/pages/GroupPageV2/Tabs/Projects/GroupProjectsEditTab.vue new file mode 100644 index 000000000..b7743364a --- /dev/null +++ b/src/pages/GroupPageV2/Tabs/Projects/GroupProjectsEditTab.vue @@ -0,0 +1,59 @@ + + + diff --git a/src/pages/GroupPageV2/Tabs/Projects/GroupProjectsTab.vue b/src/pages/GroupPageV2/Tabs/Projects/GroupProjectsTab.vue new file mode 100644 index 000000000..fbc4fc0a5 --- /dev/null +++ b/src/pages/GroupPageV2/Tabs/Projects/GroupProjectsTab.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/skeletons/base.skeletons.ts b/src/skeletons/base.skeletons.ts new file mode 100644 index 000000000..b01fd84fb --- /dev/null +++ b/src/skeletons/base.skeletons.ts @@ -0,0 +1,22 @@ +import { DEFAULT_PAGINATION_LIMIT, PaginationResult } from '@/composables/usePagination' + +export const maxSkeleton = (elementCount: number, limit: number | null): number => { + const sanLimit = limit ?? DEFAULT_PAGINATION_LIMIT + return Math.min(elementCount ?? sanLimit, sanLimit) +} + +export const factoriesSkeleton = (element: () => T, number: number): T[] => { + return Array.from(Array(maxSkeleton(number, DEFAULT_PAGINATION_LIMIT))).map(() => element()) +} + +export const factoryPagination = ( + element: () => T, + number: number = DEFAULT_PAGINATION_LIMIT +): PaginationResult => { + const results = factoriesSkeleton(element, number) + + return { + count: results.length, + results, + } +} diff --git a/src/skeletons/crisalid.skeletons.ts b/src/skeletons/crisalid.skeletons.ts new file mode 100644 index 000000000..1f40d715c --- /dev/null +++ b/src/skeletons/crisalid.skeletons.ts @@ -0,0 +1,46 @@ +import { Document, Identifier, ResearcherDocumentAnalytics } from '@/interfaces/researcher' +import { factoriesSkeleton } from '@/skeletons/base.skeletons' +import { randomInt } from 'es-toolkit' + +export const documentAnalyticsSkeleton = ( + def?: Partial +): ResearcherDocumentAnalytics => ({ + document_types: { + Book: randomInt(10), + Grant: randomInt(10), + Note: randomInt(10), + }, + years: [ + { year: 2020, total: randomInt(10) }, + { year: 2021, total: randomInt(10) }, + { year: 2022, total: randomInt(10) }, + { year: 2023, total: randomInt(10) }, + { year: 2024, total: randomInt(10) }, + { year: 2025, total: randomInt(10) }, + { year: 2026, total: randomInt(10) }, + ], + roles: { + actor: randomInt(10), + client: randomInt(10), + funder: randomInt(10), + }, + ...(def || {}), +}) + +export const identifierSkeleton = (def?: Partial): Omit => ({ + value: 'lorem', + harvester: 'hal', + ...(def || {}), +}) + +export const researchDocumentSkeleton = (def?: Partial): Omit => ({ + title: 'Ipsum nostrud officia dolor esse exercitation mollit.', + description: 'Ipsum nostrud officia dolor esse exercitation mollit.', + document_type: 'Book', + contributors: [], + // @ts-expect-error ignore not id + identifiers: factoriesSkeleton(identifierSkeleton, randomInt(5)), + publication_date: null, + similars: 0, + ...(def || {}), +}) diff --git a/src/skeletons/group.skeletons.ts b/src/skeletons/group.skeletons.ts new file mode 100644 index 000000000..124acc222 --- /dev/null +++ b/src/skeletons/group.skeletons.ts @@ -0,0 +1,50 @@ +import { GroupMember } from '@/models/group.model' +import { PeopleGroupModel } from '@/models/invitation.model' + +export const groupSkeleton = (def?: Partial): Omit => ({ + slug: 'slug', + name: 'name', + description: 'Esse culpa qui quis ea aliqua commodo reprehenderit minim elit dolore amet Lorem.', + short_description: + 'Esse culpa qui quis ea aliqua commodo reprehenderit minim elit dolore amet Lorem.', + email: '', + type: 'type', + header_image: null, + publication_status: 'public', + organization: null, + hierarchy: [], + sdgs: [], + tags: [], + children: [], + modules: { + members: 0, + featured_projects: 0, + publications: 0, + conferences: 0, + similars: 0, + subgroups: 0, + }, + ...(def || {}), +}) + +export const memberSkeleton = (def?: Partial): Omit => ({ + name: { + firstname: 'firstname', + lastname: 'lastname', + }, + slug: 'string', + email: 'email@email.fr', + roles: [], + orgs: [], + given_name: 'given_name', + family_name: 'family_name', + permissions: [], + description: 'description', + resources: { + files: 0, + links: 0, + }, + is_manager: false, + is_leader: false, + ...(def || {}), +}) diff --git a/src/skeletons/project.skeletons.ts b/src/skeletons/project.skeletons.ts new file mode 100644 index 000000000..d6d4cce0a --- /dev/null +++ b/src/skeletons/project.skeletons.ts @@ -0,0 +1,44 @@ +import { ProjectModel } from '@/models/project.model' +import { TagModel } from '@/models/tag.model' +import { factoriesSkeleton } from '@/skeletons/base.skeletons' +import { randomInt } from 'es-toolkit' + +export const tagSkeleton = (def?: Partial): Omit => ({ + title: 'Occaecat', + title_fr: 'Occaecat', + title_en: 'Occaecat', + description: 'Adipisicing magna qui est esse do ipsum nostrud ut dolor.', + description_en: 'Anim cupidatat nulla deserunt aliqua magna enim occaecat quis cupidatat Lorem.', + description_fr: + 'Velit id fugiat sint occaecat ad laborum reprehenderit eu minim ut Lorem pariatur nulla voluptate.', + ...(def || {}), +}) + +export const projectSkeleton = (def?: Partial): Omit => ({ + title: 'title', + description: 'Elit veniam consectetur sunt officia.', + header_image: null, + is_locked: false, + is_shareable: false, + purpose: 'Elit veniam consectetur sunt officia.', + language: 'fr', + locations: [], + publication_status: 'public', + life_status: 'completed', + reviews: [], + // @ts-expect-error no id in tags + tags: factoriesSkeleton(tagSkeleton, randomInt(3)), + is_followed: { + is_followed: false, + follow_id: null, + }, + follows: [], + links: [], + files: [], + announcements: [], + blog_entries: [], + goals: [], + slug: 'slug', + updated_at: '', + ...(def || {}), +}) From c00fe0331ccdd75a3e713891303476244d7d8ec3 Mon Sep 17 00:00:00 2001 From: rgermain Date: Wed, 18 Feb 2026 11:17:22 +0100 Subject: [PATCH 02/12] refactor(group): refactor group modules --- src/analytics/location.analytic.ts | 8 +- src/api/follows.service.ts | 6 +- src/api/sanitizes/researcher.ts | 18 +- src/api/v2/group.service.ts | 2 - src/app/router.options.ts | 2 +- src/app/useAdminPagesRoutes.ts | 4 +- src/app/useGroupPagesRoutes.ts | 26 +- src/components/base/form/ImageInput.vue | 6 +- src/components/base/form/TextInput.vue | 3 +- src/components/base/media/CroppedApiImage.vue | 1 + .../NewsfeedAnnouncementsItem.vue | 1 + .../ApproveTermsModal/ApproveTermsModal.vue | 2 +- .../GroupMemberItem/GroupMemberItem.vue | 143 -------- .../people/Researcher/ResearcherDocument.vue | 14 +- .../Researcher/ResearcherDocumentSimilars.vue | 68 ++-- .../Researcher/ResearcherDocumentsList.vue | 6 +- .../ResearcherDocumentsListBase.vue | 4 +- .../people/TeamCard/TeamCardInline.vue | 101 ++---- src/components/people/UserCard.vue | 29 +- .../ProjectMemberSection.vue | 112 ------ src/components/project/TeamSection.vue | 16 +- src/components/sdgs/SdgList.vue | 2 + src/composables/useAPI.ts | 3 +- src/composables/useAutoTranslate.ts | 31 +- src/composables/useGroupMembersUpdate.ts | 6 +- src/composables/useGroupProjectsUpdate.ts | 19 +- src/composables/useLpiHead.ts | 51 ++- src/functs/IconImage.ts | 1 + src/functs/followUtils.ts | 3 +- src/i18n/locales/ca.json | 7 +- src/i18n/locales/de.json | 7 +- src/i18n/locales/en.json | 7 +- src/i18n/locales/es.json | 7 +- src/i18n/locales/et.json | 7 +- src/i18n/locales/fr.json | 7 +- src/i18n/locales/nl.json | 7 +- src/models/invitation.model.ts | 54 ++- src/pages/GroupPageV2/GroupPage.vue | 330 ++++++++++++++++-- .../GroupPageV2/Tabs/GroupSnapshotTab.vue | 302 +++------------- src/pages/GroupsPage/GroupsPage.vue | 129 +++---- .../Tabs/ProfileGroupsEditTab.vue | 1 - .../Tabs/ProfileGroupsTab.vue | 1 - .../Tabs/ProfileSummaryTab.vue | 8 +- .../Tabs/ResearcherDocumentsTab.vue | 7 +- src/plugins/lang-switch.ts | 4 +- src/stores/useOrganizations.ts | 9 + src/stores/useProjects.ts | 4 +- .../GroupMemberItem/GroupMemberItem.spec.ts | 2 +- 48 files changed, 758 insertions(+), 830 deletions(-) delete mode 100644 src/components/people/GroupMemberItem/GroupMemberItem.vue delete mode 100644 src/components/project/ProjectMemberSection/ProjectMemberSection.vue diff --git a/src/analytics/location.analytic.ts b/src/analytics/location.analytic.ts index 52de3fb08..eb6d9829e 100644 --- a/src/analytics/location.analytic.ts +++ b/src/analytics/location.analytic.ts @@ -1,15 +1,11 @@ import analytics from '@/analytics/index' -import { LocationType } from '@/models/types' +import { ProjectLocationForm } from '@/models/location.model' export interface LocationAnalytic { project: { id: string } - location: { - lat: number - lng: number - type: LocationType - } + location: ProjectLocationForm } export default { diff --git a/src/api/follows.service.ts b/src/api/follows.service.ts index 52b9643b9..ab91ae67e 100644 --- a/src/api/follows.service.ts +++ b/src/api/follows.service.ts @@ -1,6 +1,7 @@ import type { AddManyFollowedProject, FollowInput, + FollowProjectOutput, // FollowOutput, // FollowOutputList, } from '@/models/follow.model' @@ -16,7 +17,10 @@ export async function getUserFollows(body: FollowInput, params) { } export async function postFollow(follow: FollowInput) { - return await useAPI(`project/${follow.project_id}/follow/`, { body: follow, method: 'POST' }) + return await useAPI(`project/${follow.project_id}/follow/`, { + body: follow, + method: 'POST', + }) //.data.value } diff --git a/src/api/sanitizes/researcher.ts b/src/api/sanitizes/researcher.ts index 24ca84bfe..c7a7435a0 100644 --- a/src/api/sanitizes/researcher.ts +++ b/src/api/sanitizes/researcher.ts @@ -44,7 +44,8 @@ type AnalyticsYears = { * @exports */ export const sanitizeResearcherDocumentAnalyticsYears = ( - data: ResearcherDocumentAnalytics['years'] + data: ResearcherDocumentAnalytics['years'], + limit?: number ): AnalyticsYears => { const info: AnalyticsYears = { minYear: null, @@ -52,12 +53,6 @@ export const sanitizeResearcherDocumentAnalyticsYears = ( bar: [], } data.forEach((o) => { - if (info.minYear == null || info.minYear > o.year) { - info.minYear = o.year - } - if (info.maxYear == null || info.maxYear < o.year) { - info.maxYear = o.year - } info.bar.push({ count: o.total, year: o.year, @@ -65,13 +60,18 @@ export const sanitizeResearcherDocumentAnalyticsYears = ( }) }) + info.bar = info.bar.toSorted((a, b) => a.year - b.year) + if (limit) { + info.bar = info.bar.slice(-limit) + } + info.minYear = info.bar.at(0).year + info.maxYear = info.bar.at(-1).year + const maxCount = Math.max(...info.bar.map((el) => el.count)) info.bar.forEach((obj) => { obj.height = (obj.count / maxCount) * 100 }) - info.bar = info.bar.reverse() - return info } diff --git a/src/api/v2/group.service.ts b/src/api/v2/group.service.ts index d886ee847..7695aa184 100644 --- a/src/api/v2/group.service.ts +++ b/src/api/v2/group.service.ts @@ -5,8 +5,6 @@ import { getGroupMember as fetchGetGroupMember, getGroupSimilar as fetchGetGroupSimilar, getSubGroup as fetchGetSubGroup, - getGroupLocation as fetchLocationsGroup, - getGroupGallery as fetchGroupGallery, } from '@/api/groups.service' import useAsyncAPI from '@/composables/useAsyncAPI' import useAsyncPaginationAPI from '@/composables/useAsyncPaginationAPI' diff --git a/src/app/router.options.ts b/src/app/router.options.ts index df939e34a..02a9b8b2f 100644 --- a/src/app/router.options.ts +++ b/src/app/router.options.ts @@ -223,7 +223,7 @@ const routes = ({ { path: '/create-group', name: 'createGroup', - component: () => import('../pages/CreateEditGroupPage/CreateEditGroupPage.vue'), + component: () => import('../pages/GroupPageV2/Tabs/GroupEditTab.vue'), meta: { resetScroll: true, diff --git a/src/app/useAdminPagesRoutes.ts b/src/app/useAdminPagesRoutes.ts index f40ae039f..d5a963d19 100644 --- a/src/app/useAdminPagesRoutes.ts +++ b/src/app/useAdminPagesRoutes.ts @@ -103,7 +103,7 @@ export default function useAdminPagesRoutes() { { path: 'create', name: 'adminCreateGroup', - component: () => import('../pages/CreateEditGroupPage/CreateEditGroupPage.vue'), + component: () => import('../pages/GroupPageV2/Tabs/GroupEditTab.vue'), props: { postCancelRouteFactory: () => ({ name: 'groupsList' }), postCreateRouteFactory: () => ({ name: 'groupsList' }), @@ -120,7 +120,7 @@ export default function useAdminPagesRoutes() { postCreateRouteFactory: () => ({ name: 'groupsList' }), postUpdateRouteFactory: () => ({ name: 'groupsList' }), }), - component: () => import('../pages/CreateEditGroupPage/CreateEditGroupPage.vue'), + component: () => import('../pages/GroupPageV2/Tabs/GroupEditTab.vue'), }, ], }, diff --git a/src/app/useGroupPagesRoutes.ts b/src/app/useGroupPagesRoutes.ts index a88bc5b46..10975e914 100644 --- a/src/app/useGroupPagesRoutes.ts +++ b/src/app/useGroupPagesRoutes.ts @@ -15,12 +15,28 @@ export default function useGroupPagesRoutes() { { path: 'members', name: 'groupMembers', - component: () => import('../pages/GroupPageV2/Tabs/GroupMembersTab.vue'), + component: () => import('../pages/GroupPageV2/Tabs/Members/GroupMembersTab.vue'), }, { path: 'projects', name: 'groupProjects', - component: () => import('../pages/GroupPageV2/Tabs/GroupProjectsTab.vue'), + component: () => import('../pages/GroupPageV2/Tabs/Projects/GroupProjectsTab.vue'), + }, + { + path: 'publications', + name: 'groupPublications', + component: () => import('../pages/GroupPageV2/Tabs/Documents/GroupDocumentsTab.vue'), + props: () => ({ + documentType: 'publications', + }), + }, + { + path: 'conferences', + name: 'groupConferences', + component: () => import('../pages/GroupPageV2/Tabs/Documents/GroupDocumentsTab.vue'), + props: () => ({ + documentType: 'conferences', + }), }, // retro compat { @@ -36,17 +52,17 @@ export default function useGroupPagesRoutes() { isReducedMode: true, groupId: route.params.groupId, }), - component: () => import('../pages/CreateEditGroupPage/CreateEditGroupPage.vue'), + component: () => import('../pages/GroupPageV2/Tabs/GroupEditTab.vue'), }, { path: 'members/edit', name: 'groupMembersEdit', - component: () => import('../pages/GroupPageV2/Tabs/GroupMembersEditTab.vue'), + component: () => import('../pages/GroupPageV2/Tabs/Members/GroupMembersEditTab.vue'), }, { path: 'projects/edit', name: 'groupProjectsEdit', - component: () => import('../pages/GroupPageV2/Tabs/GroupProjectsEditTab.vue'), + component: () => import('../pages/GroupPageV2/Tabs/Projects/GroupProjectsEditTab.vue'), }, ], props: true, diff --git a/src/components/base/form/ImageInput.vue b/src/components/base/form/ImageInput.vue index 43fbfd268..8f5ee52bc 100644 --- a/src/components/base/form/ImageInput.vue +++ b/src/components/base/form/ImageInput.vue @@ -58,6 +58,8 @@ const props = withDefaults( } ) +const { t } = useNuxtI18n() + const emit = defineEmits<{ 'upload-image': [File] 'upload-images': [File[]] @@ -70,9 +72,9 @@ const displayedLabel = computed(() => { return props.label } if (props.existingImage) { - return $t('picture.change-picture') + return t('picture.change-picture') } - return $t('picture.add-picture') + return t('picture.add-picture') }) const labelRef = useTemplateRef('label') diff --git a/src/components/base/form/TextInput.vue b/src/components/base/form/TextInput.vue index 9a1dd23be..d8e67722c 100644 --- a/src/components/base/form/TextInput.vue +++ b/src/components/base/form/TextInput.vue @@ -29,6 +29,7 @@ :disabled="disabled" :data-test="dataTest" :maxlength="maxLength" + @change="$emit('change', $event)" @keydown.enter="$emit('enter')" @focus="$emit('focus', $event)" @blur="$emit('blur', $event)" @@ -122,7 +123,7 @@ export default { }, }, - emits: ['update:modelValue', 'enter', 'focus', 'blur'], + emits: ['update:modelValue', 'enter', 'focus', 'blur', 'change'], data() { return { diff --git a/src/components/base/media/CroppedApiImage.vue b/src/components/base/media/CroppedApiImage.vue index ed6448ed4..dfb476e02 100644 --- a/src/components/base/media/CroppedApiImage.vue +++ b/src/components/base/media/CroppedApiImage.vue @@ -11,6 +11,7 @@ - - diff --git a/src/components/people/Researcher/ResearcherDocument.vue b/src/components/people/Researcher/ResearcherDocument.vue index e02e08cbb..1653936f2 100644 --- a/src/components/people/Researcher/ResearcherDocument.vue +++ b/src/components/people/Researcher/ResearcherDocument.vue @@ -1,11 +1,11 @@ diff --git a/src/components/project/ProjectMemberSection/ProjectMemberSection.vue b/src/components/project/ProjectMemberSection/ProjectMemberSection.vue deleted file mode 100644 index 54056a0e9..000000000 --- a/src/components/project/ProjectMemberSection/ProjectMemberSection.vue +++ /dev/null @@ -1,112 +0,0 @@ - - - - - diff --git a/src/components/project/TeamSection.vue b/src/components/project/TeamSection.vue index 3cccdf7f4..46b53f74b 100644 --- a/src/components/project/TeamSection.vue +++ b/src/components/project/TeamSection.vue @@ -21,8 +21,8 @@ v-for="user in projectUsers" :key="user?.user.id" :role-label="roleLabel(user.role)" - :user="user.user" - @user-clicked="removeUser(user)" + :member="user.user" + @click="removeUser(user)" /> @@ -133,12 +133,12 @@ export default { roleLabel(role) { if (role) { - if (role === 'owners') return 'role.editor' - else if (role === 'members') return 'role.teammate' - else if (role === 'reviewers') return 'role.reviewer' - else if (role === 'owner_groups') return 'role.editor-groups' - else if (role === 'reviewer_groups') return 'role.reviewer-groups' - else if (role === 'member_groups') return 'role.teammate-groups' + if (role === 'owners') return this.$t('role.editor') + else if (role === 'members') return this.$t('role.teammate') + else if (role === 'reviewers') return this.$t('role.reviewer') + else if (role === 'owner_groups') return this.$t('role.editor-groups') + else if (role === 'reviewer_groups') return this.$t('role.reviewer-groups') + else if (role === 'member_groups') return this.$t('role.teammate-groups') } return null }, diff --git a/src/components/sdgs/SdgList.vue b/src/components/sdgs/SdgList.vue index 8dac40dd0..99f327640 100644 --- a/src/components/sdgs/SdgList.vue +++ b/src/components/sdgs/SdgList.vue @@ -7,6 +7,8 @@ - + diff --git a/src/pages/GroupPageV2/Tabs/GroupSnapshotTab.vue b/src/pages/GroupPageV2/Tabs/GroupSnapshotTab.vue index 989748f18..13669ce1e 100644 --- a/src/pages/GroupPageV2/Tabs/GroupSnapshotTab.vue +++ b/src/pages/GroupPageV2/Tabs/GroupSnapshotTab.vue @@ -1,270 +1,72 @@ - diff --git a/src/pages/GroupsPage/GroupsPage.vue b/src/pages/GroupsPage/GroupsPage.vue index 9ce8a6652..21cb5ce93 100644 --- a/src/pages/GroupsPage/GroupsPage.vue +++ b/src/pages/GroupsPage/GroupsPage.vue @@ -1,29 +1,47 @@ - + diff --git a/src/pages/UserProfilePageV2/Tabs/ProfileGroupsTab.vue b/src/pages/UserProfilePageV2/Tabs/ProfileGroupsTab.vue index 4d42148ad..225fe3af6 100644 --- a/src/pages/UserProfilePageV2/Tabs/ProfileGroupsTab.vue +++ b/src/pages/UserProfilePageV2/Tabs/ProfileGroupsTab.vue @@ -18,7 +18,6 @@ v-if="cardListSlotProps.item" :class="{ 'is-other-org': groupIsOtherOrg(cardListSlotProps.item) }" :group="cardListSlotProps.item" - :title="groupIsOtherOrg(cardListSlotProps.item) ? t('group.is-other-org') : ''" @navigated-away="emit('close')" @click.capture="cancelIfOtherOrg($event, cardListSlotProps.item)" /> diff --git a/src/pages/UserProfilePageV2/Tabs/ProfileSummaryTab.vue b/src/pages/UserProfilePageV2/Tabs/ProfileSummaryTab.vue index 0b768f24e..f265b7f9b 100644 --- a/src/pages/UserProfilePageV2/Tabs/ProfileSummaryTab.vue +++ b/src/pages/UserProfilePageV2/Tabs/ProfileSummaryTab.vue @@ -26,7 +26,7 @@ :to="{ name: 'ResearcherPublicationsOther', params: { userId: user.id } }" /> - - ({{ documentsCount }}) - +
{{ documentEmpty }}
@@ -14,14 +14,15 @@ - - diff --git a/tests/factories/group.factory.ts b/tests/factories/group.factory.ts index a926f8d37..e057e672e 100644 --- a/tests/factories/group.factory.ts +++ b/tests/factories/group.factory.ts @@ -1,6 +1,9 @@ import { createFactory } from 'faker-create-factory' import BaseFactory from './base.factory' import { GroupModel, GroupModelInput } from '@/models/group.model' +import { PeopleGroupModel, TranslatedPeopleGroupModel } from '@/models/invitation.model' +import { ImageFactory } from './image.factory' +import { OrganizationOutputFactory } from './organization.factory' export const groupFactory = createFactory((faker) => ({ ...BaseFactory.generate(), @@ -13,3 +16,38 @@ export const groupFactory = createFactory((faker) => ({ export const groupInputFactory = createFactory((faker) => ({ user_ids: [], })) + +export const peopleGroupFactory = createFactory((faker) => ({ + ...BaseFactory.generate(), + id: faker.datatype.number(), + slug: faker.name.title(), + name: faker.name.title(), + description: faker.lorem.text(100), + short_description: faker.lorem.text(20), + email: faker.internet.email(), + type: faker.datatype.string(), + header_image: ImageFactory.generate(), + publication_status: faker.datatype.string(), + organization: OrganizationOutputFactory.generate(), + children: [], + modules: { + members: 0, + featured_projects: 0, + publications: 0, + conferences: 0, + subgroups: 0, + similars: 0, + }, + sdgs: [], + tags: [], + hierarchy: null, +})) + +export const groupTranslatedFactory = createFactory((faker) => ({ + ...peopleGroupFactory.generate(), + $t: { + name: faker.name.title(), + description: faker.lorem.text(100), + short_description: faker.lorem.text(20), + }, +})) diff --git a/tests/unit/components/group/GroupHeader/GroupHeaderV2.spec.ts b/tests/unit/components/group/GroupHeader/GroupHeaderV2.spec.ts deleted file mode 100644 index bea1bad4a..000000000 --- a/tests/unit/components/group/GroupHeader/GroupHeaderV2.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { lpiMount } from '@/../tests/helpers/LpiMount' -import english from '@/i18n/locales/en.json' -import GroupHeaderV2 from '@/components/group/GroupHeader/GroupHeaderV2.vue' -import { beforeEach, describe, expect, it } from 'vitest' - -const i18n = { - locale: 'en', - fallbackLocale: 'en', - messages: { - en: english, - }, -} - -describe('GroupHeaderV2.vue', () => { - let wrapper - let defaultParams - - beforeEach(() => { - defaultParams = { - i18n, - props: { - title: '123', - image: { - id: 0, - name: 'string', - url: 'string', - height: 2147483647, - width: 2147483647, - created_at: '2022-06-28T09:59:48.743Z', - variations: { medium: 'string.jpeg' }, - }, - visibility: 'public', - email: 'string', - isLoading: false, - shortDescription: 'string', - }, - } - }) - - it('should render GroupHeaderV2 component', () => { - wrapper = lpiMount(GroupHeaderV2, defaultParams) - expect(wrapper.exists()).toBe(true) - }) -}) diff --git a/tests/unit/components/project/ProjectHeader.spec.ts b/tests/unit/components/project/ProjectHeader.spec.ts index ab90d15ad..b633f8bc4 100644 --- a/tests/unit/components/project/ProjectHeader.spec.ts +++ b/tests/unit/components/project/ProjectHeader.spec.ts @@ -1,6 +1,6 @@ import { lpiShallowMount } from '@/../tests/helpers/LpiMount' import english from '@/i18n/locales/en.json' -import ProjectHeader from '@/components/project/ProjectHeader.vue' +import ProjectHeader from '@/components/project/ProjectHeaderV2.vue' import { ProjectFactory, ProjectOutputFactory } from '@/../tests/factories/project.factory' import MockComponent from '@/../tests/helpers/MockComponent.vue' diff --git a/tests/unit/pages/GroupPage/GroupPageInnerV2.spec.ts b/tests/unit/pages/GroupPage/GroupPageInnerV2.spec.ts index 6dc15e277..6d6d3f2a8 100644 --- a/tests/unit/pages/GroupPage/GroupPageInnerV2.spec.ts +++ b/tests/unit/pages/GroupPage/GroupPageInnerV2.spec.ts @@ -1,191 +1,42 @@ -import GroupPageInnerV2 from '@/components/group/GroupPageInnerV2.vue' -import { lpiShallowMount } from '@/../tests/helpers/LpiMount' -import { loadLocaleMessages } from '@/../tests/helpers/loadLocaleMessages' -import { flushPromises } from '@vue/test-utils' - -import MockComponent from '@/../tests/helpers/MockComponent.vue' -import { getGroup, getGroupMember, getGroupProject } from '@/api/groups.service' - -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { Mock } from 'vitest' - -import pinia from '@/stores' -import usePeopleGroupsStore from '@/stores/usePeopleGroups' -import useOrganizationsStore from '@/stores/useOrganizations' -import useUsersStore from '@/stores/useUsers' - -import useGroupPagesRoutes from '@/app/useGroupPagesRoutes' - -import { OrganizationOutput, OrganizationPatchInput } from '@/models/organization.model' - -vi.mock('@/api/groups.service', () => ({ - getGroup: vi.fn().mockResolvedValue({ - id: 123, - permissions: [], // TODO: remove from model - users: [], // TODO: remove from model - name: 'string', - description: 'string', - email: 'group@test.com', - type: 'group', - organization: 'TEST', - managers: [], - members: [], - hierarchy: [], - children: [], - projects: [], - header_image: { variations: { medium: 'string.jpeg' } }, - logo_image: null, - publication_status: 'public', - }), - getGroupMember: vi.fn().mockResolvedValue({ results: [] }), - getGroupProject: vi.fn().mockResolvedValue({ results: [] }), -})) - -const i18n = { - locale: 'en', - fallbackLocale: 'en', - messages: loadLocaleMessages(), -} - -const router = useGroupPagesRoutes() - -const route = { - name: 'groupSnapshot', +import { lpiMount } from '@/../tests/helpers/LpiMount' +import { describe, expect, it } from 'vitest' +import { mockNuxtImport, registerEndpoint } from '@nuxt/test-utils/runtime' +import GroupPage from '@/pages/GroupPageV2/GroupPage.vue' +import { peopleGroupFactory } from '../../../factories/group.factory' + +const group = peopleGroupFactory.generate() +mockNuxtImport('useRoute', () => () => ({ params: { - groupId: 123, - }, -} - -const buildParams = (groupId) => ({ - i18n, - router: [ - { path: '/', name: 'home', component: MockComponent }, - { path: '/page404', name: 'page404', component: MockComponent }, - ], - props: { - groupId, - }, - global: { - mocks: { - $route: route, - }, + groupId: group.id, }, -}) - -describe('GroupPageInnerV2', () => { - let usersStore - beforeEach(() => { - usePeopleGroupsStore(pinia) - const organizationsStore = useOrganizationsStore(pinia) - organizationsStore._current = { code: 'TEST' } as unknown as OrganizationOutput - - usersStore = useUsersStore(pinia) - usersStore.id = 123 - usersStore.userFromApi = {} - usersStore.permissions = {} - usersStore.getUser = vi.fn() - }) - afterEach(() => { - // usersStore.$reset() - }) - it('should render GroupPageInnerV2 component', () => { - let wrapper = lpiShallowMount(GroupPageInnerV2, buildParams('123')) - - expect(wrapper.exists()).toBeTruthy() - }) +})) - it('should load group data', async () => { - let wrapper = lpiShallowMount(GroupPageInnerV2, buildParams('123')) - let vm: any = wrapper.vm - expect(vm.isLoading).toBe(true) - await flushPromises() - expect(getGroup).toHaveBeenCalled() - expect(getGroupMember).toHaveBeenCalled() - expect(getGroupProject).toHaveBeenCalled() - expect(vm.isLoading).toBe(false) - }) - // TODO: Fix this test since migrating people group store to pinia - // it('should display a 404 if no group found', async () => { - // vi.mocked(getGroup).mockRejectedValueOnce({ response: { status: 404 } }) - // let wrapper = lpiShallowMount(GroupPageInnerV2, buildParams('123')) - // await (wrapper.vm as any).$nextTick() // Wait for component to be fully mounted - // vi.spyOn((wrapper.vm as any).$router, 'replace') - // await flushPromises() - // expect((wrapper.vm as any).$router.replace).toHaveBeenCalledWith({ - // name: 'page404', - // params: { - // pathMatch: [''], - // }, - // }) - // }) +describe('GroupProjectsTab', () => { + const orgaCode = useOrganizationCode() - it('should not display a edit button button if not allowed', async () => { - let wrapper = lpiShallowMount(GroupPageInnerV2, buildParams('123')) + it('Render', async () => { + registerEndpoint(`organization/${orgaCode}/people-group/${group.id}/`, () => group) + const wrapper = lpiMount(GroupPage, { + props: { + group, + isLoading: false, + }, + }) - let vm = wrapper.vm - await flushPromises() - expect(wrapper.find('.can-edit-group').exists()).toBe(false) + expect(wrapper.exists()).toBe(true) }) - it('should display a edit button button if allowed', async () => { - usersStore.permissions = { - 'organizations.change_peoplegroup': true, - } - let wrapper = lpiShallowMount(GroupPageInnerV2, buildParams('123')) - let vm = wrapper.vm - await flushPromises() - expect(wrapper.find('.can-edit-group').exists()).toBe(true) + it('Error fetch', async () => { + registerEndpoint(`organization/${orgaCode}/people-group/${group.id}/`, () => { + throw createError({ status: 500 }) + }) + const wrapper = lpiMount(GroupPage, { + props: { + group, + isLoading: false, + }, + }) + // @ts-expect-error TS2349 + await expect.poll(() => wrapper.text()).includes('An error occured') }) - // TODO: test somewhere else (navpanel ?) - // it('should display a breadcrumb if group has parents', async () => { - // vi.mocked(getGroup).mockResolvedValue({ - // id: 123, - // permissions: [], // TODO: remove from model - // users: [], // TODO: remove from model - // name: 'string', - // description: 'string', - // email: 'group@test.com', - // type: 'group', - // organization: 'TEST', - // managers: [], - // members: [], - // hierarchy: [{ id: 1, name: 'parent', children: [] }], - // children: [], - // projects: [], - // header_image: { variations: { medium: 'string.jpeg' } }, - // logo_image: null, - // publication_status: 'public', - // }) - - // let wrapper = lpiShallowMount(GroupPageInnerV2, buildParams('123')) - - // await flushPromises() - // expect(wrapper.find('bread-crumbs-stub').exists()).toBe(true) - // }) - - // TODO: test somewhere else (groupsbapshotab ?) - // it('should display subgroups if group has children', async () => { - // vi.mocked(getGroup).mockResolvedValue({ - // id: 123, - // permissions: [], // TODO: remove from model - // users: [], // TODO: remove from model - // name: 'string', - // description: 'string', - // email: 'group@test.com', - // type: 'group', - // organization: 'TEST', - // managers: [], - // members: [], - // hierarchy: [], - // children: [{ id: 1, name: 'child', children: [] }], - // projects: [], - // header_image: { variations: { medium: 'string.jpeg' } }, - // logo_image: null, - // publication_status: 'public', - // }) - // let wrapper = lpiShallowMount(GroupPageInnerV2, buildParams('123')) - - // await flushPromises() - // expect(wrapper.find('sub-groups-stub').exists()).toBe(true) - // }) }) diff --git a/tests/unit/pages/GroupPage/Tabs/GroupMembersTab.spec.ts b/tests/unit/pages/GroupPage/Tabs/GroupMembersTab.spec.ts index 3d1331b63..027e77087 100644 --- a/tests/unit/pages/GroupPage/Tabs/GroupMembersTab.spec.ts +++ b/tests/unit/pages/GroupPage/Tabs/GroupMembersTab.spec.ts @@ -1,76 +1,56 @@ -import GroupMembersTab from '@/pages/GroupPageV2/Tabs/GroupMembersTab.vue' -import { lpiShallowMount } from '@/../tests/helpers/LpiMount' -import { loadLocaleMessages } from '@/../tests/helpers/loadLocaleMessages' -import { DOMWrapper, flushPromises } from '@vue/test-utils' -import MockComponent from '@/../tests/helpers/MockComponent.vue' - -import pinia from '@/stores' -import useOrganizationsStore from '@/stores/useOrganizations' -import useUsersStore from '@/stores/useUsers' - -import { OrganizationOutput, OrganizationPatchInput } from '@/models/organization.model' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { Mock } from 'vitest' - -const i18n = { - locale: 'en', - fallbackLocale: 'en', - messages: loadLocaleMessages(), -} - -const protoPropsLoading = () => ({ - membersInitialRequest: {}, - - isMembersLoading: true, -}) - -const protoPropsLoaded = (members = []) => ({ - membersInitialRequest: { count: members.length, results: members }, - - isMembersLoading: false, -}) - -const buildParams = (props) => ({ - i18n, - router: [ - { path: '/', name: 'home', component: MockComponent }, - { path: '/page404', name: 'page404', component: MockComponent }, - ], - props, -}) - -describe('GroupMembersTab', () => { - beforeEach(() => { - const usersStore = useUsersStore(pinia) - usersStore.$patch({ - id: 123, - userFromApi: {}, - permissions: {}, - getUser: vi.fn(), - } as any) - const organizationsStore = useOrganizationsStore(pinia) - organizationsStore._current = { code: 'TEST' } as unknown as OrganizationOutput +import GroupMembersTab from '@/pages/GroupPageV2/Tabs/Members/GroupMembersTab.vue' +import { lpiMount } from '@/../tests/helpers/LpiMount' + +import { describe, expect, it } from 'vitest' +import { groupTranslatedFactory } from '../../../../factories/group.factory' +import { flushPromises } from '@vue/test-utils' +import { registerEndpoint } from '@nuxt/test-utils/runtime' +import GroupMemberFactory from '../../../../factories/group-member.factory' +import { PaginationsFactory } from '../../../../factories/paginations.factory' +import UserCard from '@/components/people/UserCard.vue' + +describe('GroupProjectsTab', () => { + const orgaCode = useOrganizationCode() + + it('Render', async () => { + const group = groupTranslatedFactory.generate() + registerEndpoint(`organization/${orgaCode}/people-group/${group.id}/member/`, () => { + return PaginationsFactory.generate({ + results: [ + GroupMemberFactory.generate(), + GroupMemberFactory.generate(), + GroupMemberFactory.generate(), + GroupMemberFactory.generate(), + ], + }) + }) + + const wrapper = lpiMount(GroupMembersTab, { + props: { + group, + isLoading: false, + }, + }) + + // 4 number of factory + await flushPromises() + await expect.poll(() => wrapper.findAllComponents(UserCard).length).toBe(4) }) - it('should render GroupMembersTab component', () => { - let wrapper = lpiShallowMount(GroupMembersTab, buildParams(protoPropsLoading())) - - expect(wrapper.exists()).toBeTruthy() - }) - - it('should display memeber count when loaded', async () => { - let wrapper = lpiShallowMount(GroupMembersTab, buildParams(protoPropsLoading())) - - expect(wrapper.find('.members-header .title span').exists()).toBe(false) - - wrapper.setProps(protoPropsLoaded([{ id: 1 }, { id: 2 }])) - - await wrapper.vm.$nextTick() - - let counter = wrapper.find('.members-header .title span') - - expect(counter.exists()).toBe(true) - - expect(counter.html()).toContain('2') + it('Error fetch', async () => { + const group = groupTranslatedFactory.generate() + registerEndpoint(`organization/${orgaCode}/people-group/${group.id}/member/`, () => { + throw createError({ statusCode: 500 }) + }) + + const wrapper = lpiMount(GroupMembersTab, { + props: { + group, + isLoading: false, + }, + }) + + // @ts-expect-error TS2349 + await expect.poll(() => wrapper.text()).includes('An error occured') }) }) diff --git a/tests/unit/pages/GroupPage/Tabs/GroupProjectsTab.spec.ts b/tests/unit/pages/GroupPage/Tabs/GroupProjectsTab.spec.ts index fc3da1a83..32ccf08f7 100644 --- a/tests/unit/pages/GroupPage/Tabs/GroupProjectsTab.spec.ts +++ b/tests/unit/pages/GroupPage/Tabs/GroupProjectsTab.spec.ts @@ -1,77 +1,55 @@ -import GroupProjectsTab from '@/pages/GroupPageV2/Tabs/GroupProjectsTab.vue' -import { lpiShallowMount } from '@/../tests/helpers/LpiMount' +import GroupProjectsTab from '@/pages/GroupPageV2/Tabs/Projects/GroupProjectsTab.vue' +import { lpiMount } from '@/../tests/helpers/LpiMount' import { loadLocaleMessages } from '@/../tests/helpers/loadLocaleMessages' -import { DOMWrapper, flushPromises } from '@vue/test-utils' -import MockComponent from '@/../tests/helpers/MockComponent.vue' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { Mock } from 'vitest' - -import pinia from '@/stores' -import useOrganizationsStore from '@/stores/useOrganizations' -import useUsersStore from '@/stores/useUsers' - -import { OrganizationOutput, OrganizationPatchInput } from '@/models/organization.model' -const i18n = { - locale: 'en', - fallbackLocale: 'en', - messages: loadLocaleMessages(), -} - -const protoPropsLoading = () => ({ - projectsInitialRequest: {}, - - isProjectsLoading: true, -}) - -const protoPropsLoaded = (projects = []) => ({ - projectsInitialRequest: { count: projects.length, results: projects }, - - isProjectsLoading: false, -}) - -const buildParams = (props) => ({ - i18n, - router: [ - { path: '/', name: 'home', component: MockComponent }, - { path: '/page404', name: 'page404', component: MockComponent }, - ], - props, -}) +import { describe, expect, it } from 'vitest' +import { groupTranslatedFactory } from '../../../../factories/group.factory' +import { registerEndpoint } from '@nuxt/test-utils/runtime' +import { ProjectFactory } from '../../../../factories/project.factory' +import { PaginationsFactory } from '../../../../factories/paginations.factory' +import ProjectPreview from '@/components/project/ProjectPreview.vue' describe('GroupProjectsTab', () => { - beforeEach(() => { - const usersStore = useUsersStore(pinia) - usersStore.$patch({ - id: 123, - userFromApi: {}, - permissions: {}, - getUser: vi.fn(), - } as any) - const organizationsStore = useOrganizationsStore(pinia) - organizationsStore.$patch({ - current: { code: 'TEST' } as unknown as OrganizationOutput, - } as any) - }) - it('should render GroupProjectsTab component', () => { - let wrapper = lpiShallowMount(GroupProjectsTab, buildParams(protoPropsLoading())) - - expect(wrapper.exists()).toBeTruthy() + const orgaCode = useOrganizationCode() + + it('Render', async () => { + const group = groupTranslatedFactory.generate() + registerEndpoint(`organization/${orgaCode}/people-group/${group.id}/project/`, () => { + return PaginationsFactory.generate({ + results: [ + ProjectFactory.generate(), + ProjectFactory.generate(), + ProjectFactory.generate(), + ProjectFactory.generate(), + ], + }) + }) + + const wrapper = lpiMount(GroupProjectsTab, { + props: { + group, + isLoading: false, + }, + }) + + // 4 number of factory + await expect.poll(() => wrapper.findAllComponents(ProjectPreview).length).toBe(4) }) - it('should display project count when loaded', async () => { - let wrapper = lpiShallowMount(GroupProjectsTab, buildParams(protoPropsLoading())) - - expect(wrapper.find('.projects-header .title span').exists()).toBe(false) - - wrapper.setProps(protoPropsLoaded([{ id: 1 }, { id: 2 }])) - - await wrapper.vm.$nextTick() - - let counter = wrapper.find('.projects-header .title span') - - expect(counter.exists()).toBe(true) - - expect(counter.html()).toContain('2') + it('Error fetch', async () => { + const group = groupTranslatedFactory.generate() + registerEndpoint(`organization/${orgaCode}/people-group/${group.id}/project/`, () => { + throw createError({ statusCode: 500 }) + }) + + const wrapper = lpiMount(GroupProjectsTab, { + props: { + group, + isLoading: false, + }, + }) + + // @ts-expect-error TS2349 + await expect.poll(() => wrapper.text()).includes('An error occured') }) }) diff --git a/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts b/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts index ecb57311b..59bb2b864 100644 --- a/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts +++ b/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts @@ -1,102 +1,68 @@ import GroupSnapshotTab from '@/pages/GroupPageV2/Tabs/GroupSnapshotTab.vue' import { lpiShallowMount } from '@/../tests/helpers/LpiMount' -import { loadLocaleMessages } from '@/../tests/helpers/loadLocaleMessages' import { flushPromises } from '@vue/test-utils' -import MockComponent from '@/../tests/helpers/MockComponent.vue' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { Mock } from 'vitest' +import { describe, expect, it } from 'vitest' -import pinia from '@/stores' -import useOrganizationsStore from '@/stores/useOrganizations' -import useUsersStore from '@/stores/useUsers' - -import { OrganizationOutput, OrganizationPatchInput } from '@/models/organization.model' -const i18n = { - locale: 'en', - fallbackLocale: 'en', - messages: loadLocaleMessages(), -} - -const protoPropsLoading = () => ({ - description: '', - - projectsInitialRequest: {}, - - membersInitialRequest: {}, - - isProjectsLoading: true, - - isMembersLoading: true, - - isLoading: true, -}) - -const protoPropsLoaded = (members = [], projects = []) => ({ - description: '

lorem ipsum

', - - projectsInitialRequest: { count: projects.length, results: projects }, - - membersInitialRequest: { count: members.length, results: members }, - - isProjectsLoading: false, - - isMembersLoading: false, - - isLoading: false, -}) - -const buildParams = (props) => ({ - i18n, - router: [ - { path: '/', name: 'home', component: MockComponent }, - { path: '/page404', name: 'page404', component: MockComponent }, - ], - props, -}) +import { groupTranslatedFactory } from '../../../../factories/group.factory' +import { groupSkeleton } from '@/skeletons/group.skeletons' +import GroupProjectsPreview from '@/components/group/Modules/Projects/GroupProjectsPreview.vue' +import GroupMembersPreview from '@/components/group/Modules/Members/GroupMembersPreview.vue' +import GroupDescriptionPreview from '@/components/group/Modules/Extras/GroupDescriptionPreview.vue' +import GroupSimilarsPreview from '@/components/group/Modules/Extras/GroupSimilarsPreview.vue' +import GroupSubPreview from '@/components/group/Modules/GroupSub/GroupSubPreview.vue' +import GroupDocumentsPreview from '@/components/group/Modules/Documents/GroupDocumentsPreview.vue' +import OrganizationTagFactory from '../../../../factories/tag.factory' describe('GroupSnapshotTab', () => { - beforeEach(() => { - const usersStore = useUsersStore(pinia) - usersStore.$patch({ - id: 123, - userFromApi: {}, - permissions: {}, - getUser: vi.fn(), - } as any) - - const organizationsStore = useOrganizationsStore(pinia) - organizationsStore.$patch({ - current: { code: 'TEST' } as unknown as OrganizationOutput, - } as any) - }) - it('should render GroupSnapshotTab component', () => { - let wrapper = lpiShallowMount(GroupSnapshotTab, buildParams(protoPropsLoading())) - - expect(wrapper.exists()).toBeTruthy() - }) - - it('should display loading state then render', async () => { - let wrapper = lpiShallowMount(GroupSnapshotTab, buildParams(protoPropsLoading())) - - expect(wrapper.find('.skeleton').exists()).toBe(true) - expect(wrapper.find('.projects .see-more-button').exists()).toBe(false) - expect(wrapper.find('.members .see-more-button').exists()).toBe(false) - - wrapper.setProps(protoPropsLoaded([{ id: 1 }], [{ id: 2 }])) - - await wrapper.vm.$nextTick() - - expect(wrapper.find('.skeleton').exists()).toBe(false) - expect(wrapper.find('.projects .see-more-button').exists()).toBe(true) - expect(wrapper.find('.members .see-more-button').exists()).toBe(true) - }) - - it("should not display list section when there's no project or member", async () => { - let wrapper = lpiShallowMount(GroupSnapshotTab, buildParams(protoPropsLoaded([], []))) - - expect(wrapper.find('.skeleton').exists()).toBe(false) - expect(wrapper.find('.projects').exists()).toBe(false) - expect(wrapper.find('.members').exists()).toBe(false) + it('display modules', async () => { + const group = groupTranslatedFactory.generate(groupSkeleton()) + group.sdgs = [1, 2, 3, 4, 5] + group.tags = [ + OrganizationTagFactory.generate(), + OrganizationTagFactory.generate(), + OrganizationTagFactory.generate(), + ] + group.$t.description = '' + + console.log(group) + + const wrapper = lpiShallowMount(GroupSnapshotTab, { + props: { + group, + }, + }) + + expect(wrapper.findComponent(GroupDescriptionPreview).exists()).toBe(false) + expect(wrapper.findComponent(GroupSimilarsPreview).exists()).toBe(false) + expect(wrapper.findComponent(GroupMembersPreview).exists()).toBe(false) + expect(wrapper.findComponent(GroupSubPreview).exists()).toBe(false) + expect(wrapper.findComponent(GroupMembersPreview).exists()).toBe(false) + expect(wrapper.findComponent(GroupProjectsPreview).exists()).toBe(false) + expect(wrapper.findComponent(GroupDocumentsPreview).exists()).toBe(false) + + // add modules numbers + const newGroup = groupTranslatedFactory.generate() + newGroup.modules.featured_projects = 6 + newGroup.modules.members = 8 + newGroup.modules.conferences = 8 + newGroup.modules.publications = 8 + newGroup.modules.similars = 8 + newGroup.modules.subgroups = 8 + newGroup.$t.description = 'description' + + wrapper.setProps({ + group: newGroup, + }) + + await flushPromises() + + expect(wrapper.findComponent(GroupDescriptionPreview).exists()).toBe(true) + expect(wrapper.findComponent(GroupSimilarsPreview).exists()).toBe(true) + expect(wrapper.findComponent(GroupMembersPreview).exists()).toBe(true) + expect(wrapper.findComponent(GroupSubPreview).exists()).toBe(true) + expect(wrapper.findComponent(GroupMembersPreview).exists()).toBe(true) + expect(wrapper.findComponent(GroupProjectsPreview).exists()).toBe(true) + expect(wrapper.findComponent(GroupDocumentsPreview).exists()).toBe(true) }) }) From 9fad5497c234bea2719025b0fe203718c2f65e64 Mon Sep 17 00:00:00 2001 From: rgermain Date: Wed, 18 Feb 2026 13:30:53 +0100 Subject: [PATCH 05/12] missing files --- src/components/group/GroupCard.vue | 166 ++++++++---------- src/components/group/GroupForm/GroupForm.vue | 67 +++++-- .../group/GroupForm/GroupTeamSection.vue | 15 +- .../group/GroupForm/ParentGroupSection.vue | 53 +++--- .../group/GroupForm/ProjectSection.vue | 22 ++- .../GroupSelectDrawer/GroupSelectDrawer.vue | 2 +- .../group/GroupsElement/GroupsElement.vue | 2 +- src/components/group/Modules/GroupHeader.vue | 18 +- .../Modules/Members/BaseGroupMembersList.vue | 18 +- .../Modules/Members/GroupMemberDrawer.vue | 31 ++++ tests/factories/project.factory.ts | 15 +- .../group/GroupForm/ProjectSection.spec.ts | 4 +- 12 files changed, 239 insertions(+), 174 deletions(-) create mode 100644 src/components/group/Modules/Members/GroupMemberDrawer.vue diff --git a/src/components/group/GroupCard.vue b/src/components/group/GroupCard.vue index 6866870cd..d61f93bb3 100644 --- a/src/components/group/GroupCard.vue +++ b/src/components/group/GroupCard.vue @@ -4,6 +4,7 @@ :to-link="toLink" :data-test="`group-card-${group.name}`" :mode="mode" + :line-clamp="lineClamp" @click="toGroupPage" > - @@ -80,7 +73,7 @@ const confirmGroup = (group) => { .group-grid { display: grid; - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr; justify-items: stretch; gap: $space-l; } diff --git a/src/components/group/GroupForm/ProjectSection.vue b/src/components/group/GroupForm/ProjectSection.vue index 46b86026f..d17369531 100644 --- a/src/components/group/GroupForm/ProjectSection.vue +++ b/src/components/group/GroupForm/ProjectSection.vue @@ -15,14 +15,18 @@
- + @click="onRemoveProject(project)" + > + +
diff --git a/src/server/routes/geocoding.ts b/src/server/routes/geocoding.ts index 34d7ef2c3..d1dbf4144 100644 --- a/src/server/routes/geocoding.ts +++ b/src/server/routes/geocoding.ts @@ -24,7 +24,7 @@ async function fetchFromPhoton(address, locale, runtimeConfig) { lat, lng, description: '', - type: 'team', + type: 'address', } satisfies Geocoding }) @@ -55,7 +55,7 @@ async function fetchFromGoogle(address, locale, runtimeConfig) { lat, lng, description: '', - type: 'team', + type: 'address', } satisfies Geocoding }) return suggestedLocations diff --git a/src/skeletons/group.skeletons.ts b/src/skeletons/group.skeletons.ts index 124acc222..405f0fd4e 100644 --- a/src/skeletons/group.skeletons.ts +++ b/src/skeletons/group.skeletons.ts @@ -15,6 +15,7 @@ export const groupSkeleton = (def?: Partial): Omit): Omit((faker) => ({ ...BaseFactory.generate(), @@ -37,14 +38,17 @@ export const peopleGroupFactory = createFactory((faker) => ({ conferences: 0, subgroups: 0, similars: 0, + locations: 0, }, sdgs: [], tags: [], + location: null, hierarchy: null, })) export const groupTranslatedFactory = createFactory((faker) => ({ ...peopleGroupFactory.generate(), + location: BaseTranslatedLocationFactory.generate(), $t: { name: faker.name.title(), description: faker.lorem.text(100), diff --git a/tests/factories/location.factory.ts b/tests/factories/location.factory.ts index 1f791e483..ddc30c6ed 100644 --- a/tests/factories/location.factory.ts +++ b/tests/factories/location.factory.ts @@ -1,6 +1,6 @@ import { createFactory } from 'faker-create-factory' -import { LocationModel } from '@/models/location.model' +import { BaseTranslatedLocationModel, LocationModel } from '@/models/location.model' import BaseFactory from './base.factory' const LocationFactory = createFactory((faker) => ({ @@ -14,4 +14,21 @@ const LocationFactory = createFactory((faker) => ({ project: null, })) +export const BaseTranslatedLocationFactory = createFactory( + (faker) => ({ + ...BaseFactory.generate(), + id: faker.datatype.number(), + title: faker.lorem.text(), + description: faker.lorem.text(), + lat: Number(faker.address.latitude()), + lng: Number(faker.address.longitude()), + type: 'team', + project: null, + $t: { + title: faker.lorem.text(), + description: faker.lorem.text(), + }, + }) +) + export default LocationFactory diff --git a/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts b/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts index 59bb2b864..4d688cd8e 100644 --- a/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts +++ b/tests/unit/pages/GroupPage/Tabs/GroupSnapshotTab.spec.ts @@ -13,6 +13,7 @@ import GroupSimilarsPreview from '@/components/group/Modules/Extras/GroupSimilar import GroupSubPreview from '@/components/group/Modules/GroupSub/GroupSubPreview.vue' import GroupDocumentsPreview from '@/components/group/Modules/Documents/GroupDocumentsPreview.vue' import OrganizationTagFactory from '../../../../factories/tag.factory' +import GroupLocationPreview from '@/components/group/Modules/Locations/GroupLocationPreview.vue' describe('GroupSnapshotTab', () => { it('display modules', async () => { @@ -40,6 +41,7 @@ describe('GroupSnapshotTab', () => { expect(wrapper.findComponent(GroupMembersPreview).exists()).toBe(false) expect(wrapper.findComponent(GroupProjectsPreview).exists()).toBe(false) expect(wrapper.findComponent(GroupDocumentsPreview).exists()).toBe(false) + expect(wrapper.findComponent(GroupLocationPreview).exists()).toBe(false) // add modules numbers const newGroup = groupTranslatedFactory.generate() @@ -49,6 +51,7 @@ describe('GroupSnapshotTab', () => { newGroup.modules.publications = 8 newGroup.modules.similars = 8 newGroup.modules.subgroups = 8 + newGroup.modules.locations = 8 newGroup.$t.description = 'description' wrapper.setProps({ @@ -64,5 +67,6 @@ describe('GroupSnapshotTab', () => { expect(wrapper.findComponent(GroupMembersPreview).exists()).toBe(true) expect(wrapper.findComponent(GroupProjectsPreview).exists()).toBe(true) expect(wrapper.findComponent(GroupDocumentsPreview).exists()).toBe(true) + expect(wrapper.findComponent(GroupLocationPreview).exists()).toBe(true) }) }) From 6af7758fd75786028f6fb08682a02e384ace6d52 Mon Sep 17 00:00:00 2001 From: rgermain Date: Wed, 18 Feb 2026 13:50:28 +0100 Subject: [PATCH 07/12] fix missings things --- src/components/map/LocationForm.vue | 4 ++++ src/i18n/locales/ca.json | 4 +++- src/i18n/locales/de.json | 4 +++- src/i18n/locales/es.json | 4 +++- src/i18n/locales/et.json | 4 +++- src/i18n/locales/fr.json | 4 +++- src/i18n/locales/nl.json | 4 +++- 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/components/map/LocationForm.vue b/src/components/map/LocationForm.vue index 0efec98a5..92186e755 100644 --- a/src/components/map/LocationForm.vue +++ b/src/components/map/LocationForm.vue @@ -78,6 +78,10 @@ const locationTypeOptions = computed(() => { value: 'impact', label: t('location.impact'), }, + { + value: 'address', + label: t('location.address'), + }, ] if (props.locationTypes) { return arr.filter(({ value }) => props.locationTypes.includes(value)) diff --git a/src/i18n/locales/ca.json b/src/i18n/locales/ca.json index 173415a68..f03a0f5a9 100644 --- a/src/i18n/locales/ca.json +++ b/src/i18n/locales/ca.json @@ -1011,7 +1011,9 @@ "conferences": "Conferèncias", "publications": "Publicacions", "similars": "Grups similars", - "presentation": "Presentació" + "presentation": "Presentació", + "locations": "Ubicacions", + "location": "Adreça" }, "header": { "private": "Privat: només visible per als membres de l' equip", diff --git a/src/i18n/locales/de.json b/src/i18n/locales/de.json index 04f99542e..96daa8526 100644 --- a/src/i18n/locales/de.json +++ b/src/i18n/locales/de.json @@ -1011,7 +1011,9 @@ "conferences": "Konferenzen", "publications": "Veröffentlichungen", "similars": "Gruppen ähnliche", - "presentation": "Präsentation" + "presentation": "Präsentation", + "locations": "Standorte", + "location": "Anschrift" }, "header": { "private": "Private: nur für Teammitglieder sichtbar", diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json index d3448b2b6..04fc384fe 100644 --- a/src/i18n/locales/es.json +++ b/src/i18n/locales/es.json @@ -1011,7 +1011,9 @@ "conferences": "Conferencias", "publications": "Publicaciones", "similars": "Grupos similares", - "presentation": "Presentación" + "presentation": "Presentación", + "locations": "Lugares", + "location": "Dirección" }, "header": { "private": "Privada: visible sólo a los miembros del equipo", diff --git a/src/i18n/locales/et.json b/src/i18n/locales/et.json index 5a80c7e50..245798744 100644 --- a/src/i18n/locales/et.json +++ b/src/i18n/locales/et.json @@ -1011,7 +1011,9 @@ "conferences": "Konverentsid", "publications": "Trükised", "similars": "Rühmad sarnased", - "presentation": "Esitlus" + "presentation": "Esitlus", + "locations": "Asukohad", + "location": "Aadress" }, "header": { "private": "Privaatne: nähtav ainult meeskonnaliikmetele", diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index 29de6bf91..105277fe5 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -1011,7 +1011,9 @@ "conferences": "Conférences", "publications": "Publications", "similars": "Groupes similaires", - "presentation": "Présentation" + "presentation": "Présentation", + "locations": "Emplacements", + "location": "Adresse" }, "header": { "private": "Privée: visible uniquement par les membres de l’équipe", diff --git a/src/i18n/locales/nl.json b/src/i18n/locales/nl.json index 9ca397af3..77a461c0b 100644 --- a/src/i18n/locales/nl.json +++ b/src/i18n/locales/nl.json @@ -1011,7 +1011,9 @@ "conferences": "Conferenties", "publications": "Publicaties", "similars": "Groepen vergelijkbaar", - "presentation": "Presentatie" + "presentation": "Presentatie", + "locations": "Locaties", + "location": "Adres" }, "header": { "private": "Privé: alleen zichtbaar voor teamleden", From a6385cd74e200c8b521896d18e498cd0d8d2bb38 Mon Sep 17 00:00:00 2001 From: rgermain Date: Wed, 18 Feb 2026 18:07:50 +0100 Subject: [PATCH 08/12] fix: reviews --- src/components/group/GroupForm/GroupTeamSection.vue | 1 - src/components/group/Map/GroupLocationToolTip.vue | 6 ------ 2 files changed, 7 deletions(-) diff --git a/src/components/group/GroupForm/GroupTeamSection.vue b/src/components/group/GroupForm/GroupTeamSection.vue index 28d449687..761e69d3d 100644 --- a/src/components/group/GroupForm/GroupTeamSection.vue +++ b/src/components/group/GroupForm/GroupTeamSection.vue @@ -139,7 +139,6 @@ export default { this.$emit('update:model-value', team) }, openDrawer(mode) { - console.log(this.teamModalMode) this.teamModalMode = mode this.teamModalVisible = true }, diff --git a/src/components/group/Map/GroupLocationToolTip.vue b/src/components/group/Map/GroupLocationToolTip.vue index 370b73cb7..02cc7bd06 100644 --- a/src/components/group/Map/GroupLocationToolTip.vue +++ b/src/components/group/Map/GroupLocationToolTip.vue @@ -17,10 +17,4 @@ import { DEFAULT_GROUP_PATATOID } from '@/composables/usePatatoids' import CardLocationTooltip from '@/components/map/CardLocationTooltip.vue' const props = defineProps<{ location: AnyTranslatedLocation; group: TranslatedPeopleGroupModel }>() - -watch( - () => props.group, - () => console.log(props.group), - { immediate: true } -) From d3b70af8d3ca9d5639b5b0304e37d676b78f1de3 Mon Sep 17 00:00:00 2001 From: rgermain Date: Wed, 18 Feb 2026 18:15:26 +0100 Subject: [PATCH 09/12] linter --- src/components/group/Map/GroupLocationToolTip.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/group/Map/GroupLocationToolTip.vue b/src/components/group/Map/GroupLocationToolTip.vue index 02cc7bd06..729cbd18f 100644 --- a/src/components/group/Map/GroupLocationToolTip.vue +++ b/src/components/group/Map/GroupLocationToolTip.vue @@ -16,5 +16,5 @@ import { TranslatedPeopleGroupModel } from '@/models/invitation.model' import { DEFAULT_GROUP_PATATOID } from '@/composables/usePatatoids' import CardLocationTooltip from '@/components/map/CardLocationTooltip.vue' -const props = defineProps<{ location: AnyTranslatedLocation; group: TranslatedPeopleGroupModel }>() +defineProps<{ location: AnyTranslatedLocation; group: TranslatedPeopleGroupModel }>() From 0faafbcfcd649972650647cceeb7d21d2b694337 Mon Sep 17 00:00:00 2001 From: rgermain Date: Fri, 20 Feb 2026 14:39:40 +0100 Subject: [PATCH 10/12] change OneToOne to Fk --- src/api/groups.service.ts | 61 +++++++++++++- src/api/v2/group.service.ts | 6 +- src/components/group/GroupForm/GroupForm.vue | 80 +++++++++++++------ src/components/group/Modules/GroupHeader.vue | 8 +- .../Modules/Locations/GroupLocationBase.vue | 5 +- .../Locations/GroupLocationPreview.vue | 8 +- src/components/map/GeneralMap.vue | 7 +- src/components/map/LocationList.vue | 4 +- src/composables/useAutoTranslate.ts | 4 +- src/i18n/locales/ca.json | 2 +- src/i18n/locales/de.json | 2 +- src/i18n/locales/en.json | 5 +- src/i18n/locales/es.json | 2 +- src/i18n/locales/et.json | 2 +- src/i18n/locales/fr.json | 2 +- src/i18n/locales/nl.json | 2 +- src/models/invitation.model.ts | 14 ++-- src/pages/GroupPageV2/GroupPage.vue | 6 +- src/pages/GroupPageV2/Tabs/GroupEditTab.vue | 10 +-- .../GroupPageV2/Tabs/GroupSnapshotTab.vue | 6 +- .../Tabs/Locations/GroupLocationsTab.vue | 4 +- src/skeletons/group.skeletons.ts | 4 +- tests/factories/group.factory.ts | 8 +- tests/factories/location.factory.ts | 9 ++- .../GroupPage/Tabs/GroupSnapshotTab.spec.ts | 2 +- 25 files changed, 180 insertions(+), 83 deletions(-) diff --git a/src/api/groups.service.ts b/src/api/groups.service.ts index fe35fbe83..094936570 100644 --- a/src/api/groups.service.ts +++ b/src/api/groups.service.ts @@ -11,7 +11,7 @@ import { _adaptParamsToGetQuery } from '@/api/utils.service' import useAPI from '@/composables/useAPI' import { ProjectModel } from '@/models/project.model' import { PeopleGroupModel } from '@/models/invitation.model' -import { LocationModel } from '@/models/location.model' +import { BaseLocationModel, LocationModel } from '@/models/location.model' // HIERARCHY export async function getHierarchyGroups(organizationCode: string, config = {}) { @@ -169,9 +169,68 @@ export async function getSubGroup(organizationCode: string, groupId: number, con ) } +export async function getGroupProjectsLocation( + organizationCode: string, + groupId: number, + config = {} +) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/projects-locations/`, + config + ) +} + export async function getGroupLocation(organizationCode: string, groupId: number, config = {}) { return await useAPI>( `organization/${organizationCode}/people-group/${groupId}/locations/`, config ) } + +export async function removeGroupLocation( + organizationCode: string, + groupId: number, + locationId: number, + config = {} +) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/locations/${locationId}/`, + { + ...config, + method: 'DELETE', + } + ) +} + +export async function patchGroupLocation( + organizationCode: string, + groupId: number, + locationId: number, + payload: Partial, + config = {} +) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/locations/${locationId}/`, + { + ...config, + body: payload, + method: 'PATCH', + } + ) +} + +export async function postGroupLocation( + organizationCode: string, + groupId: number, + payload: BaseLocationModel, + config = {} +) { + return await useAPI>( + `organization/${organizationCode}/people-group/${groupId}/locations/`, + { + ...config, + body: payload, + method: 'POST', + } + ) +} diff --git a/src/api/v2/group.service.ts b/src/api/v2/group.service.ts index 75320d29e..68a4e3d73 100644 --- a/src/api/v2/group.service.ts +++ b/src/api/v2/group.service.ts @@ -5,7 +5,7 @@ import { getGroupMember as fetchGetGroupMember, getGroupSimilar as fetchGetGroupSimilar, getSubGroup as fetchGetSubGroup, - getGroupLocation as fetchLocationsGroup, + getGroupProjectsLocation as fetchGroupProjectsLocation, } from '@/api/groups.service' import useAsyncAPI from '@/composables/useAsyncAPI' import useAsyncPaginationAPI from '@/composables/useAsyncPaginationAPI' @@ -144,7 +144,7 @@ export const getSubGroup = ( ) } -export const getGroupLocation = ( +export const getGroupProjectsLocation = ( organizationCode: RefOrRaw, groupId: RefOrRaw, config = {} @@ -155,7 +155,7 @@ export const getGroupLocation = ( return useAsyncAPI( key, ({ config }) => - fetchLocationsGroup(unref(organizationCode), unref(groupId), { + fetchGroupProjectsLocation(unref(organizationCode), unref(groupId), { ...DEFAULT_CONFIG, ...config, }), diff --git a/src/components/group/GroupForm/GroupForm.vue b/src/components/group/GroupForm/GroupForm.vue index f57fe6aad..4bdd08899 100644 --- a/src/components/group/GroupForm/GroupForm.vue +++ b/src/components/group/GroupForm/GroupForm.vue @@ -81,7 +81,7 @@