mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
feat(webapp): add location distance in group profile (#8846)
* Add distance to group profile if location is defined * Fix snapshot tests in 'webapp/pages/groups/_id/_slug.spec.js' * Fix prop Vue warning in test 'webapp/pages/groups/_id/_slug.spec.js' * reuse locationFragement for groups * use better order on locationFragement parameters * moved LocationInfo Component to correct place as its used in Group & User related context * use size prop * reduce changeset * update snapshots * remove computed property & simplify component * more tests & updated snapshots --------- Co-authored-by: Ulf Gebhardt <ulf.gebhardt@webcraft-media.de>
This commit is contained in:
parent
f61850980e
commit
c1a05bc73b
45
webapp/components/LocationInfo/LocationInfo.spec.js
Normal file
45
webapp/components/LocationInfo/LocationInfo.spec.js
Normal file
@ -0,0 +1,45 @@
|
||||
import { render } from '@testing-library/vue'
|
||||
import LocationInfo from './LocationInfo.vue'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('LocationInfo', () => {
|
||||
const Wrapper = ({ withDistance }) => {
|
||||
return render(LocationInfo, {
|
||||
localVue,
|
||||
propsData: {
|
||||
locationData: {
|
||||
name: 'Paris',
|
||||
distanceToMe: withDistance ? 100 : null,
|
||||
},
|
||||
},
|
||||
mocks: {
|
||||
$t: jest.fn((t) => t),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
describe('distance', () => {
|
||||
it('renders with distance', () => {
|
||||
const wrapper = Wrapper({ withDistance: true })
|
||||
expect(wrapper.container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('renders without distance', () => {
|
||||
const wrapper = Wrapper({ withDistance: false })
|
||||
expect(wrapper.container).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe('size', () => {
|
||||
it('renders in base size', () => {
|
||||
const wrapper = Wrapper({ size: 'base' })
|
||||
expect(wrapper.container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('renders in small size', () => {
|
||||
const wrapper = Wrapper({ size: 'small' })
|
||||
expect(wrapper.container).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<div class="location-info">
|
||||
<div :class="`location-info size-${size}`">
|
||||
<div class="location">
|
||||
<base-icon name="map-marker" />
|
||||
{{ locationData.name }}
|
||||
</div>
|
||||
<div v-if="distance" class="distance">{{ distance }}</div>
|
||||
<div v-if="locationData.distanceToMe !== null" class="distance">
|
||||
{{ $t('location.distance', { distance: locationData.distanceToMe }) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -13,12 +15,12 @@ export default {
|
||||
name: 'LocationInfo',
|
||||
props: {
|
||||
locationData: { type: Object, default: null },
|
||||
},
|
||||
computed: {
|
||||
distance() {
|
||||
return this.locationData.distanceToMe === null
|
||||
? null
|
||||
: this.$t('location.distance', { distance: this.locationData.distanceToMe })
|
||||
size: {
|
||||
type: String,
|
||||
default: 'base',
|
||||
validator: (value) => {
|
||||
return value.match(/(small|base)/)
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -36,9 +38,21 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.distance {
|
||||
.size-base {
|
||||
> .distance {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.size-small {
|
||||
font-size: 0.8rem;
|
||||
color: #70677e;
|
||||
margin-bottom: 12px;
|
||||
|
||||
> .distance {
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,99 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LocationInfo distance renders with distance 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="location-info size-base"
|
||||
>
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
|
||||
location.distance
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`LocationInfo distance renders without distance 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="location-info size-base"
|
||||
>
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`LocationInfo size renders in base size 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="location-info size-base"
|
||||
>
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`LocationInfo size renders in small size 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="location-info size-base"
|
||||
>
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -1,31 +0,0 @@
|
||||
import { render } from '@testing-library/vue'
|
||||
import LocationInfo from './LocationInfo.vue'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('LocationInfo', () => {
|
||||
const Wrapper = ({ withDistance }) => {
|
||||
return render(LocationInfo, {
|
||||
localVue,
|
||||
propsData: {
|
||||
locationData: {
|
||||
name: 'Paris',
|
||||
distanceToMe: withDistance ? 100 : null,
|
||||
},
|
||||
},
|
||||
mocks: {
|
||||
$t: jest.fn((t) => t),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
it('renders with distance', () => {
|
||||
const wrapper = Wrapper({ withDistance: true })
|
||||
expect(wrapper.container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('renders without distance', () => {
|
||||
const wrapper = Wrapper({ withDistance: false })
|
||||
expect(wrapper.container).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
<script>
|
||||
import Badges from '~/components/Badges.vue'
|
||||
import LocationInfo from '~/components/UserTeaser/LocationInfo.vue'
|
||||
import LocationInfo from '~/components/LocationInfo/LocationInfo.vue'
|
||||
import { isTouchDevice } from '~/components/utils/isTouchDevice'
|
||||
import { userTeaserQuery } from '~/graphql/User.js'
|
||||
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`LocationInfo renders with distance 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="location-info"
|
||||
>
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
location.distance
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`LocationInfo renders without distance 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="location-info"
|
||||
>
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -16,8 +16,8 @@ export const userFragment = gql`
|
||||
}
|
||||
`
|
||||
|
||||
export const locationFragment = (lang) => gql`
|
||||
fragment location on User {
|
||||
export const locationFragment = (type, lang) => gql`
|
||||
fragment location on ${type} {
|
||||
locationName
|
||||
location {
|
||||
id
|
||||
@ -57,7 +57,7 @@ export const userCountsFragment = gql`
|
||||
|
||||
export const userTeaserFragment = (lang) => gql`
|
||||
${badgesFragment}
|
||||
${locationFragment(lang)}
|
||||
${locationFragment('User', lang)}
|
||||
|
||||
fragment userTeaser on User {
|
||||
followedByCount
|
||||
|
||||
@ -15,7 +15,7 @@ export default (i18n) => {
|
||||
return gql`
|
||||
${userFragment}
|
||||
${userCountsFragment}
|
||||
${locationFragment(lang)}
|
||||
${locationFragment('User', lang)}
|
||||
${badgesFragment}
|
||||
${postFragment}
|
||||
${postCountsFragment}
|
||||
@ -65,7 +65,7 @@ export const filterPosts = (i18n) => {
|
||||
return gql`
|
||||
${userFragment}
|
||||
${userCountsFragment}
|
||||
${locationFragment(lang)}
|
||||
${locationFragment('User', lang)}
|
||||
${badgesFragment}
|
||||
${postFragment}
|
||||
${postCountsFragment}
|
||||
@ -108,7 +108,7 @@ export const profilePagePosts = (i18n) => {
|
||||
return gql`
|
||||
${userFragment}
|
||||
${userCountsFragment}
|
||||
${locationFragment(lang)}
|
||||
${locationFragment('User', lang)}
|
||||
${badgesFragment}
|
||||
${postFragment}
|
||||
${postCountsFragment}
|
||||
@ -158,7 +158,7 @@ export const relatedContributions = (i18n) => {
|
||||
return gql`
|
||||
${userFragment}
|
||||
${userCountsFragment}
|
||||
${locationFragment(lang)}
|
||||
${locationFragment('User', lang)}
|
||||
${badgesFragment}
|
||||
${postFragment}
|
||||
${postCountsFragment}
|
||||
|
||||
@ -15,7 +15,7 @@ export const profileUserQuery = (i18n) => {
|
||||
return gql`
|
||||
${userFragment}
|
||||
${userCountsFragment}
|
||||
${locationFragment(lang)}
|
||||
${locationFragment('User', lang)}
|
||||
${badgesFragment}
|
||||
|
||||
query User($id: ID!, $followedByCount: Int!, $followingCount: Int!) {
|
||||
@ -112,7 +112,7 @@ export const mapUserQuery = (i18n) => {
|
||||
const lang = i18n.locale().toUpperCase()
|
||||
return gql`
|
||||
${userFragment}
|
||||
${locationFragment(lang)}
|
||||
${locationFragment('User', lang)}
|
||||
${badgesFragment}
|
||||
|
||||
query {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import gql from 'graphql-tag'
|
||||
// import { locationFragment } from './Fragments'
|
||||
import { locationFragment } from './Fragments'
|
||||
|
||||
// ------ mutations
|
||||
|
||||
@ -160,9 +160,8 @@ export const removeUserFromGroupMutation = () => {
|
||||
|
||||
export const groupQuery = (i18n) => {
|
||||
const lang = i18n ? i18n.locale().toUpperCase() : 'EN'
|
||||
// ${locationFragment(lang)}
|
||||
return gql`
|
||||
|
||||
${locationFragment('Group', lang)}
|
||||
query ($isMember: Boolean, $id: ID, $slug: String, $first: Int, $offset: Int) {
|
||||
Group(isMember: $isMember, id: $id, slug: $slug, first: $first, offset: $offset) {
|
||||
id
|
||||
@ -187,13 +186,7 @@ export const groupQuery = (i18n) => {
|
||||
avatar {
|
||||
url
|
||||
}
|
||||
locationName
|
||||
# ...location
|
||||
location {
|
||||
name: name${lang}
|
||||
lng
|
||||
lat
|
||||
}
|
||||
...location
|
||||
membersCount
|
||||
myRole
|
||||
inviteCodes {
|
||||
|
||||
@ -199,19 +199,30 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
<div
|
||||
class="location-info size-small"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
data-test="map-marker"
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</p>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
|
||||
location.distance
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
@ -1072,19 +1083,30 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
<div
|
||||
class="location-info size-small"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
data-test="map-marker"
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</p>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
|
||||
location.distance
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
@ -1529,19 +1551,30 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
<div
|
||||
class="location-info size-small"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
data-test="map-marker"
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</p>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
|
||||
location.distance
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
@ -2075,19 +2108,30 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a close
|
||||
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
<div
|
||||
class="location-info size-small"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
data-test="map-marker"
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</p>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Paris
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
|
||||
location.distance
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
@ -6603,19 +6647,30 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
<div
|
||||
class="location-info size-small"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
data-test="map-marker"
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Hamburg
|
||||
|
||||
</p>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Hamburg
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
|
||||
location.distance
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
@ -7582,19 +7637,30 @@ exports[`GroupProfileSlug given a puplic group – "yoga-practice" given a hidde
|
||||
|
||||
</p>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
<div
|
||||
class="location-info size-small"
|
||||
>
|
||||
<span
|
||||
class="base-icon"
|
||||
data-test="map-marker"
|
||||
<div
|
||||
class="location"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Hamburg
|
||||
|
||||
</p>
|
||||
<span
|
||||
class="base-icon"
|
||||
>
|
||||
<!---->
|
||||
</span>
|
||||
|
||||
Hamburg
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="distance"
|
||||
>
|
||||
|
||||
location.distance
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="ds-text ds-text-size-small ds-text-soft ds-text-center"
|
||||
|
||||
@ -38,10 +38,7 @@
|
||||
{{ `&${groupSlug}` }}
|
||||
</ds-text>
|
||||
<!-- group location -->
|
||||
<ds-text v-if="group && group.location" align="center" color="soft" size="small">
|
||||
<base-icon name="map-marker" data-test="map-marker" />
|
||||
{{ group && group.location ? group.location.name : '' }}
|
||||
</ds-text>
|
||||
<location-info v-if="group.location" :location-data="group.location" size="small" />
|
||||
<!-- group created at -->
|
||||
<ds-text align="center" color="soft" size="small">
|
||||
{{ $t('group.foundation') }} {{ group.createdAt | date('MMMM yyyy') }}
|
||||
@ -176,7 +173,9 @@
|
||||
? $t('group.membersListTitleNotAllowedSeeingGroupMembers')
|
||||
: null
|
||||
"
|
||||
:allProfilesCount="isAllowedSeeingGroupMembers ? group.membersCount : 0"
|
||||
:allProfilesCount="
|
||||
isAllowedSeeingGroupMembers && group.membersCount ? group.membersCount : 0
|
||||
"
|
||||
:profiles="isAllowedSeeingGroupMembers ? groupMembers : []"
|
||||
:loading="$apollo.loading"
|
||||
@fetchAllProfiles="fetchAllMembers"
|
||||
@ -280,6 +279,7 @@ import CountTo from '~/components/CountTo.vue'
|
||||
import Empty from '~/components/Empty/Empty'
|
||||
import GroupContentMenu from '~/components/ContentMenu/GroupContentMenu'
|
||||
import JoinLeaveButton from '~/components/Button/JoinLeaveButton'
|
||||
import LocationInfo from '~/components/LocationInfo/LocationInfo.vue'
|
||||
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
|
||||
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
|
||||
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
||||
@ -308,6 +308,7 @@ export default {
|
||||
Empty,
|
||||
GroupContentMenu,
|
||||
JoinLeaveButton,
|
||||
LocationInfo,
|
||||
PostTeaser,
|
||||
ProfileAvatar,
|
||||
ProfileList,
|
||||
|
||||
@ -34,11 +34,7 @@
|
||||
<!-- <base-icon name="at" data-test="at" /> -->
|
||||
{{ `@${userSlug}` }}
|
||||
</ds-text>
|
||||
<location-info
|
||||
v-if="user.location"
|
||||
:location-data="user.location"
|
||||
class="location-info"
|
||||
/>
|
||||
<location-info v-if="user.location" :location-data="user.location" size="small" />
|
||||
<ds-text align="center" color="soft" size="small">
|
||||
{{ $t('profile.memberSince') }} {{ user.createdAt | date('MMMM yyyy') }}
|
||||
</ds-text>
|
||||
@ -211,7 +207,7 @@ import { muteUser, unmuteUser } from '~/graphql/settings/MutedUsers'
|
||||
import { blockUser, unblockUser } from '~/graphql/settings/BlockedUsers'
|
||||
import UpdateQuery from '~/components/utils/UpdateQuery'
|
||||
import SocialMedia from '~/components/SocialMedia/SocialMedia'
|
||||
import LocationInfo from '~/components/UserTeaser/LocationInfo.vue'
|
||||
import LocationInfo from '~/components/LocationInfo/LocationInfo.vue'
|
||||
|
||||
const tabToFilterMapping = ({ tab, id }) => {
|
||||
return {
|
||||
@ -493,14 +489,4 @@ export default {
|
||||
margin-bottom: $space-x-small;
|
||||
}
|
||||
}
|
||||
|
||||
.location-info {
|
||||
font-size: 0.8rem;
|
||||
color: #70677e;
|
||||
margin-bottom: 12px;
|
||||
|
||||
> .distance {
|
||||
margin-top: 2px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user