diff --git a/src/api/groups.service.ts b/src/api/groups.service.ts index 3164d5830..094936570 100644 --- a/src/api/groups.service.ts +++ b/src/api/groups.service.ts @@ -11,6 +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 { BaseLocationModel, LocationModel } from '@/models/location.model' // HIERARCHY export async function getHierarchyGroups(organizationCode: string, config = {}) { @@ -167,3 +168,69 @@ export async function getSubGroup(organizationCode: string, groupId: number, con config ) } + +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/locations.services.ts b/src/api/locations.services.ts index a4300637a..88a69acec 100644 --- a/src/api/locations.services.ts +++ b/src/api/locations.services.ts @@ -1,6 +1,5 @@ import type { LocationModel, ProjectLocationForm } from '@/models/location.model' import useAPI from '@/composables/useAPI' -import utils from '@/functs/functions' import { Locations } from '@/interfaces/maps' export async function getProjectLocations(projectId: number) { @@ -11,13 +10,8 @@ export async function getProjectLocation(projectId: string, locationId: number) return await useAPI(`project/${projectId}/location/${locationId}/`) } -export async function getLocations(params, next) { - if (next) { - // TODO: nuxt check next works - return await useAPI(next, {}) //.data.value - } - - return await useAPI(`location/`, { ...utils.adaptParam(params) }) //.data.value +export async function getLocations(organizationCode: string, config = {}) { + return await useAPI(`organization/${organizationCode}/location/`, config) } export async function postLocations(projectId: string, body: ProjectLocationForm) { diff --git a/src/api/v2/group.service.ts b/src/api/v2/group.service.ts index 7695aa184..68a4e3d73 100644 --- a/src/api/v2/group.service.ts +++ b/src/api/v2/group.service.ts @@ -5,6 +5,7 @@ import { getGroupMember as fetchGetGroupMember, getGroupSimilar as fetchGetGroupSimilar, getSubGroup as fetchGetSubGroup, + getGroupProjectsLocation as fetchGroupProjectsLocation, } from '@/api/groups.service' import useAsyncAPI from '@/composables/useAsyncAPI' import useAsyncPaginationAPI from '@/composables/useAsyncPaginationAPI' @@ -142,3 +143,26 @@ export const getSubGroup = ( } ) } + +export const getGroupProjectsLocation = ( + organizationCode: RefOrRaw, + groupId: RefOrRaw, + config = {} +) => { + const { translateProjectLocations } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::group::${unref(groupId)}::locations`) + + return useAsyncAPI( + key, + ({ config }) => + fetchGroupProjectsLocation(unref(organizationCode), unref(groupId), { + ...DEFAULT_CONFIG, + ...config, + }), + { + translate: translateProjectLocations, + watch: onlyRefs([organizationCode, groupId]), + ...config, + } + ) +} diff --git a/src/api/v2/location.service.ts b/src/api/v2/location.service.ts new file mode 100644 index 000000000..606b7ec6f --- /dev/null +++ b/src/api/v2/location.service.ts @@ -0,0 +1,31 @@ +import { getLocations as fetchGetLocations } from '@/api/locations.services' +import useAsyncAPI from '@/composables/useAsyncAPI' +import { onlyRefs } from '@/functs/onlyRefs' +import { Locations } from '@/interfaces/maps' +import { RefOrRaw } from '@/interfaces/utils' +import { OrganizationModel } from '@/models/organization.model' + +const DEFAULT_CONFIG = {} + +export const getLocations = ( + organizationCode: RefOrRaw, + config = {} +) => { + const { translatePeopleGroupLocations, translateProjectLocations } = useAutoTranslate() + const key = computed(() => `${unref(organizationCode)}::locations`) + + const translateAllModel = (data: ComputedRef) => { + return computed(() => { + return { + groups: unref(translatePeopleGroupLocations(data.value?.groups)), + projects: unref(translateProjectLocations(data.value?.projects)), + } + }) + } + + return useAsyncAPI(key, () => fetchGetLocations(unref(organizationCode), { ...DEFAULT_CONFIG }), { + translate: translateAllModel, + watch: onlyRefs([organizationCode]), + ...config, + }) +} diff --git a/src/app/useGroupPagesRoutes.ts b/src/app/useGroupPagesRoutes.ts index 10975e914..486fd6a16 100644 --- a/src/app/useGroupPagesRoutes.ts +++ b/src/app/useGroupPagesRoutes.ts @@ -38,6 +38,11 @@ export default function useGroupPagesRoutes() { documentType: 'conferences', }), }, + { + path: 'locations', + name: 'groupLocations', + component: () => import('../pages/GroupPageV2/Tabs/Locations/GroupLocationsTab.vue'), + }, // retro compat { path: 'Edit', diff --git a/src/components/group/GroupForm/GroupForm.vue b/src/components/group/GroupForm/GroupForm.vue index 18e9b7256..4bdd08899 100644 --- a/src/components/group/GroupForm/GroupForm.vue +++ b/src/components/group/GroupForm/GroupForm.vue @@ -81,7 +81,7 @@
+
+ + @@ -84,6 +101,7 @@ import { TranslatedPeopleGroupModel } from '@/models/invitation.model' import BaseGroupPreview from '@/components/group/Modules/BaseGroupPreview.vue' import SdgList from '@/components/sdgs/SdgList.vue' import TagsList from '@/components/tags/TagsList.vue' +import LocationDrawer from '@/components/map/LocationDrawer.vue' import { getGroupMember } from '@/api/v2/group.service' import GroupMemberItem from '@/components/group/Modules/Members/GroupMemberItem.vue' import FetchLoader from '@/components/base/FetchLoader.vue' @@ -100,6 +118,7 @@ const props = withDefaults( ) const { t } = useNuxtI18n() +const { openModal, closeModal, stateModal } = useModal() const organizationCode = useOrganizationCode() const groupId = computed(() => props.group.id) @@ -122,8 +141,11 @@ const groupVisibilityIcon = computed(() => props.group.publication_status === 'public' ? 'Eye' : 'EyeSlash' ) +const hasLinks = computed(() => { + return props.group.locations.length +}) const hasExtras = computed(() => { - return props.group.sdgs.length + return props.group.sdgs.length || hasLinks.value }) // preview leader @@ -216,6 +238,10 @@ const closeProfile = () => (leaderIdDrawer.value = null) .group-recap-title { font-weight: bold; } + +.group-location { + cursor: pointer; +} 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..73b7c61e5 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(), @@ -30,6 +31,7 @@ export const peopleGroupFactory = createFactory((faker) => ({ publication_status: faker.datatype.string(), organization: OrganizationOutputFactory.generate(), children: [], + locations: [], modules: { members: 0, featured_projects: 0, @@ -37,6 +39,7 @@ export const peopleGroupFactory = createFactory((faker) => ({ conferences: 0, subgroups: 0, similars: 0, + projects_locations: 0, }, sdgs: [], tags: [], @@ -45,6 +48,7 @@ export const peopleGroupFactory = createFactory((faker) => ({ export const groupTranslatedFactory = createFactory((faker) => ({ ...peopleGroupFactory.generate(), + locations: BaseTranslatedLocationModelFactory.generateMany(3), $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..46231b099 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,26 @@ const LocationFactory = createFactory((faker) => ({ project: null, })) +export const BaseTranslatedLocationModelFactory = 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', + $t: { + title: faker.lorem.text(), + description: faker.lorem.text(), + }, + }) +) +export const BaseTranslatedLocationFactory = createFactory( + (faker) => ({ + ...BaseTranslatedLocationModelFactory.generate(), + project: null, + }) +) + 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..2e00abbce 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.projects_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) }) })