Merge branch '5059-epic-groups' of github.com:Ocelot-Social-Community/Ocelot-Social into 5059-groups/5501-add-group-link-to-posts-in-webapp

This commit is contained in:
Wolfgang Huß 2022-10-19 13:36:46 +02:00
commit 2eb5995116
9 changed files with 418 additions and 185 deletions

View File

@ -360,6 +360,33 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
}), }),
]) ])
// post into group
await Promise.all([
mutate({
mutation: createPostMutation(),
variables: {
id: 'p0-g0',
groupId: 'g0',
title: `What happend in Shanghai?`,
content: 'A sack of rise dropped in Shanghai. Should we further investigate?',
categoryIds: ['cat6'],
},
}),
])
authenticatedUser = await bobDerBaumeister.toJson()
await Promise.all([
mutate({
mutation: createPostMutation(),
variables: {
id: 'p1-g0',
groupId: 'g0',
title: `The man on the moon`,
content: 'We have to further investigate about the stories of a man living on the moon.',
categoryIds: ['cat12', 'cat16'],
},
}),
])
authenticatedUser = await jennyRostock.toJson() authenticatedUser = await jennyRostock.toJson()
await Promise.all([ await Promise.all([
mutate({ mutate({
@ -439,6 +466,32 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
}, },
}), }),
]) ])
// post into group
await Promise.all([
mutate({
mutation: createPostMutation(),
variables: {
id: 'p0-g1',
groupId: 'g1',
title: `Can we use ocelot for education?`,
content: 'I like the concept of this school. Can we use our software in this?',
categoryIds: ['cat8'],
},
}),
])
authenticatedUser = await peterLustig.toJson()
await Promise.all([
mutate({
mutation: createPostMutation(),
variables: {
id: 'p1-g1',
groupId: 'g1',
title: `Can we push this idea out of France?`,
content: 'This idea is too inportant to have the scope only on France.',
categoryIds: ['cat14'],
},
}),
])
authenticatedUser = await bobDerBaumeister.toJson() authenticatedUser = await bobDerBaumeister.toJson()
await Promise.all([ await Promise.all([
@ -527,6 +580,20 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
}), }),
]) ])
authenticatedUser = await louie.toJson()
await Promise.all([
mutate({
mutation: createPostMutation(),
variables: {
id: 'p0-g2',
groupId: 'g2',
title: `I am a Noob`,
content: 'I am new to Yoga and did not join this group so far.',
categoryIds: ['cat4'],
},
}),
])
// Create Posts // Create Posts
const [p0, p1, p3, p4, p5, p6, p9, p10, p11, p13, p14, p15] = await Promise.all([ const [p0, p1, p3, p4, p5, p6, p9, p10, p11, p13, p14, p15] = await Promise.all([

View File

@ -7,7 +7,6 @@
icon="ellipsis-v" icon="ellipsis-v"
size="small" size="small"
circle circle
ghost
@click.prevent="toggleMenu()" @click.prevent="toggleMenu()"
/> />
</slot> </slot>

View File

@ -1,9 +1,12 @@
import { mount } from '@vue/test-utils' import { config, mount } from '@vue/test-utils'
import GroupContentMenu from './GroupContentMenu.vue' import GroupContentMenu from './GroupContentMenu.vue'
const localVue = global.localVue const localVue = global.localVue
config.stubs['router-link'] = '<span><slot /></span>'
const propsData = { const propsData = {
usage: 'groupTeaser',
resource: {}, resource: {},
group: {}, group: {},
resourceType: 'group', resourceType: 'group',
@ -29,7 +32,7 @@ describe('GroupContentMenu', () => {
}) })
it('renders', () => { it('renders', () => {
expect(wrapper.findAll('.group-menu')).toHaveLength(1) expect(wrapper.findAll('.group-content-menu')).toHaveLength(1)
}) })
}) })
}) })

View File

@ -1,5 +1,5 @@
<template> <template>
<dropdown class="group-menu" :placement="placement" offset="5"> <dropdown class="group-content-menu" :placement="placement" offset="5">
<template #default="{ toggleMenu }"> <template #default="{ toggleMenu }">
<slot name="button" :toggleMenu="toggleMenu"> <slot name="button" :toggleMenu="toggleMenu">
<base-button <base-button
@ -40,35 +40,34 @@ export default {
Dropdown, Dropdown,
}, },
props: { props: {
placement: { type: String, default: 'bottom-end' }, usage: {
resource: { type: Object, required: true },
group: { type: Object, required: true },
resourceType: {
type: String, type: String,
required: true, required: true,
validator: (value) => { validator: (value) => {
return value.match(/(group)/) return value.match(/(groupTeaser|groupProfile)/)
}, },
}, },
group: { type: Object, required: true },
placement: { type: String, default: 'bottom-end' },
}, },
computed: { computed: {
routes() { routes() {
const routes = [] const routes = []
if (this.resourceType === 'group') { if (this.usage !== 'groupProfile') {
routes.push({ routes.push({
label: this.$t('group.contentMenu.visitGroupPage'), label: this.$t('group.contentMenu.visitGroupPage'),
icon: 'home', icon: 'home',
name: 'group-id-slug', name: 'group-id-slug',
params: { id: this.group.id, slug: this.group.slug }, params: { id: this.group.id, slug: this.group.slug },
}) })
if (this.group.myRole === 'owner') { }
routes.push({ if (this.group.myRole === 'owner') {
label: this.$t('admin.settings.name'), routes.push({
path: `/group/edit/${this.resource.id}`, label: this.$t('admin.settings.name'),
icon: 'edit', path: `/group/edit/${this.group.id}`,
}) icon: 'edit',
} })
} }
return routes return routes

View File

@ -7,79 +7,97 @@
:schema="formSchema" :schema="formSchema"
@submit="submit" @submit="submit"
> >
<ds-input <!-- "errors" is only working if you use a submit event on the form -->
:label="$t('group.name')" <template #default="{ errors }">
v-model="formData.name" <!-- group Name -->
:placeholder="`${$t('group.name')} …`" <ds-input
></ds-input> name="name"
<ds-input :label="$t('group.name')"
v-if="update" model="name"
:label="$t('group.labelSlug')" autofocus
v-model="formData.slug" :placeholder="`${$t('group.name')} …`"
icon="at" />
:placeholder="`${$t('group.labelSlug')} …`" <ds-chip size="base" :color="errors && errors.name ? 'danger' : 'medium'">
></ds-input> {{ `${formData.name.length} / ${formSchema.name.min}${formSchema.name.max}` }}
<!-- groupType --> <base-icon v-if="errors && errors.name" name="warning" />
<!-- TODO: change it has to be implemented later --> </ds-chip>
<!-- TODO: move 'ds-select' from styleguide to main code and implement missen translation etc. functionality -->
<!-- <ds-select <!-- group Slug -->
id="groupType" <ds-input
:label="$t('group.type')" v-if="update"
:v-model="formData.groupType" :label="$t('group.labelSlug')"
:label-prop="'label'" model="slug"
:options="groupTypeOptions" icon="at"
icon="user" :placeholder="`${$t('group.labelSlug')} …`"
:placeholder="$t('group.type') + ' …'" ></ds-input>
></ds-select> -->
<ds-text class="select-label"> <ds-space v-if="update" margin-top="small" />
{{ $t('group.type') }}
</ds-text> <!-- groupType -->
<ds-icon class="select-icon" name="user" /> <ds-text class="select-label">
<select {{ $t('group.type') }}
class="select" </ds-text>
:options="groupTypeOptions" <!-- TODO: change it has to be implemented later -->
:value="formData.groupType" <!-- TODO: move 'ds-select' from style guide to main code and implement missing translation etc. functionality -->
:disabled="update" <select
@change="changeGroupType($event)" class="select ds-input appearance--auto"
> name="groupType"
<option v-for="groupType in groupTypeOptions" :key="groupType" :value="groupType"> model="groupType"
{{ $t(`group.types.${groupType}`) }} :value="formData.groupType"
</option> :disabled="update"
</select> @change="changeGroupType($event)"
<!-- goal --> >
<ds-input <option v-for="groupType in groupTypeOptions" :key="groupType" :value="groupType">
:label="$t('group.goal')" {{ $t(`group.types.${groupType}`) }}
v-model="formData.about" </option>
:placeholder="$t('group.goal') + ' …'" </select>
rows="3" <ds-chip
></ds-input> size="base"
<!-- description --> :color="errors && errors.groupType && formData.groupType === '' ? 'danger' : 'medium'"
<ds-input >
:label="$t('group.description')" {{ `${formData.groupType === '' ? 0 : 1} / 1` }}
v-model="formData.description" <base-icon
:placeholder="$t('group.description') + ' …'" v-if="errors && errors.groupType && formData.groupType === ''"
type="textarea" name="warning"
rows="3" />
></ds-input> </ds-chip>
<ds-space margin-top="large">
<!-- goal -->
<ds-input
name="about"
:label="$t('group.goal')"
v-model="formData.about"
:placeholder="$t('group.goal') + ' …'"
rows="3"
/>
<ds-space margin-top="small" />
<!-- description -->
<ds-text class="select-label">
{{ $t('group.description') }}
</ds-text>
<editor
name="description"
model="description"
:users="null"
:value="formData.description"
:hashtags="null"
@input="updateEditorDescription"
/>
<ds-chip size="base" :color="errors && errors.description ? 'danger' : 'medium'">
{{ `${descriptionLength} / ${formSchema.description.min}` }}
<base-icon v-if="errors && errors.description" name="warning" />
</ds-chip>
<!-- actionRadius --> <!-- actionRadius -->
<!-- TODO: move 'ds-select' from styleguide to main code and implement missen translation etc. functionality -->
<!-- <ds-select
id="actionRadius"
:label="$t('group.actionRadius')"
v-model="formData"
model="actionRadius"
:options="['regional', 'national', 'continental', 'global']"
icon="globe"
:placeholder="`${$t('group.actionRadius')} …`"
></ds-select> -->
<ds-text class="select-label"> <ds-text class="select-label">
{{ $t('group.actionRadius') }} {{ $t('group.actionRadius') }}
</ds-text> </ds-text>
<ds-icon class="select-icon" name="globe" /> <!-- TODO: move 'ds-select' from styleguide to main code and implement missing translation etc. functionality -->
<select <select
class="select" class="select ds-input appearance--auto"
:options="actionRadiusOptions" name="actionRadius"
:value="formData.actionRadius" :value="formData.actionRadius"
@change="changeActionRadius($event)" @change="changeActionRadius($event)"
> >
@ -91,41 +109,68 @@
{{ $t(`group.actionRadii.${actionRadius}`) }} {{ $t(`group.actionRadii.${actionRadius}`) }}
</option> </option>
</select> </select>
<ds-chip
size="base"
:color="
errors && errors.actionRadius && formData.actionRadius === '' ? 'danger' : 'medium'
"
>
{{ `${formData.actionRadius === '' ? 0 : 1} / 1` }}
<base-icon
v-if="errors && errors.actionRadius && formData.actionRadius === ''"
name="warning"
/>
</ds-chip>
<!-- location --> <!-- location -->
<ds-select <ds-select
id="city" id="city"
:label="$t('settings.data.labelCity')" :label="$t('settings.data.labelCity') + locationNameLabelAddOnOldName"
v-model="formData.locationName" v-model="formData.locationName"
:options="cities" :options="cities"
icon="map-marker" icon="map-marker"
:icon-right="null"
:placeholder="$t('settings.data.labelCity') + ' …'" :placeholder="$t('settings.data.labelCity') + ' …'"
:loading="loadingGeo" :loading="loadingGeo"
@input.native="handleCityInput" @input.native="handleCityInput"
/> />
<!-- TODO: implement clear button --> <base-button
<!-- <base-button icon="close" circle ghost size="small" :disabled="formData.locationName.length === 0" @click="clear" /> --> v-if="formLocationName !== ''"
</ds-space> icon="close"
<ds-space margin-top="large"> ghost
size="small"
style="position: relative; display: inline-block; right: -96%; top: -33px; width: 26px"
@click="formData.locationName = ''"
></base-button>
<ds-space margin-top="small" />
<!-- category -->
<categories-select <categories-select
v-if="categoriesActive" v-if="categoriesActive"
model="categoryIds" model="categoryIds"
name="categoryIds"
:existingCategoryIds="formData.categoryIds" :existingCategoryIds="formData.categoryIds"
/> />
</ds-space> <ds-chip
<ds-space margin-top="large"> v-if="categoriesActive"
<nuxt-link to="/my-groups"> size="base"
<ds-button>{{ $t('actions.cancel') }}</ds-button> :color="errors && errors.categoryIds ? 'danger' : 'medium'"
</nuxt-link>
<ds-button
type="submit"
icon="save"
:disabled="update ? submitDisableEdit : submitDisable"
primary
@click.prevent="submit()"
> >
{{ update ? $t('group.update') : $t('group.save') }} {{ formData.categoryIds.length }} / 3
</ds-button> <base-icon v-if="errors && errors.categoryIds" name="warning" />
</ds-space> </ds-chip>
<!-- submit -->
<ds-space margin-top="large">
<nuxt-link to="/my-groups">
<ds-button>{{ $t('actions.cancel') }}</ds-button>
</nuxt-link>
<ds-button type="submit" icon="save" primary :disabled="checkFormError(errors)" fill>
{{ update ? $t('group.update') : $t('group.save') }}
</ds-button>
</ds-space>
</template>
</ds-form> </ds-form>
</div> </div>
</template> </template>
@ -133,7 +178,12 @@
<script> <script>
import CategoriesSelect from '~/components/CategoriesSelect/CategoriesSelect' import CategoriesSelect from '~/components/CategoriesSelect/CategoriesSelect'
import { CATEGORIES_MIN, CATEGORIES_MAX } from '~/constants/categories.js' import { CATEGORIES_MIN, CATEGORIES_MAX } from '~/constants/categories.js'
import { NAME_LENGTH_MIN, NAME_LENGTH_MAX } from '~/constants/groups.js' import {
NAME_LENGTH_MIN,
NAME_LENGTH_MAX,
DESCRIPTION_WITHOUT_HTML_LENGTH_MIN,
} from '~/constants/groups.js'
import Editor from '~/components/Editor/Editor'
import { queryLocations } from '~/graphql/location' import { queryLocations } from '~/graphql/location'
let timeout let timeout
@ -142,6 +192,7 @@ export default {
name: 'GroupForm', name: 'GroupForm',
components: { components: {
CategoriesSelect, CategoriesSelect,
Editor,
}, },
props: { props: {
update: { update: {
@ -171,17 +222,33 @@ export default {
groupType: groupType || '', groupType: groupType || '',
about: about || '', about: about || '',
description: description || '', description: description || '',
// from database 'locationName' comes as "string | null"
// 'formData.locationName':
// see 'created': tries to set it to a "requestGeoData" object and fills the menu if possible
// if user selects one from menu we get a "requestGeoData" object here
// "requestGeoData" object: "{ id: String, label: String, value: String }"
// otherwise it's a string: empty or none empty
locationName: locationName || '', locationName: locationName || '',
actionRadius: actionRadius || '', actionRadius: actionRadius || '',
categoryIds: categories ? categories.map((category) => category.id) : [], categoryIds: categories ? categories.map((category) => category.id) : [],
}, },
formSchema: { formSchema: {
name: { required: true, min: NAME_LENGTH_MIN, max: NAME_LENGTH_MAX }, name: { required: true, min: NAME_LENGTH_MIN, max: NAME_LENGTH_MAX },
slug: { required: false }, slug: { required: false, min: NAME_LENGTH_MIN },
groupType: { required: true }, groupType: { required: true, min: 1 },
about: { required: true }, about: { required: false },
description: { required: true }, description: {
actionRadius: { required: true }, type: 'string',
required: true,
min: DESCRIPTION_WITHOUT_HTML_LENGTH_MIN,
validator: (_, value = '') => {
if (this.$filters.removeHtml(value).length < this.formSchema.description.min) {
return [new Error()]
}
return []
},
},
actionRadius: { required: true, min: 1 },
locationName: { required: false }, locationName: { required: false },
categoryIds: { categoryIds: {
type: 'array', type: 'array',
@ -199,46 +266,74 @@ export default {
}, },
} }
}, },
async created() {
// set to "requestGeoData" object and fill select menu if possible
this.formData.locationName =
(await this.requestGeoData(this.formLocationName)) || this.formLocationName
},
computed: { computed: {
submitDisable() { formLocationName() {
return ( const isNestedValue =
this.formData.name === '' || typeof this.formData.locationName === 'object' &&
this.formData.groupType === '' || typeof this.formData.locationName.value === 'string'
// this.formData.about === '' || // not mandatory const isDirectString = typeof this.formData.locationName === 'string'
this.formData.description === '' || return isNestedValue
this.formData.actionRadius === '' || ? this.formData.locationName.value
// this.formData.locationName === '' || // not mandatory : isDirectString
this.formData.categoryIds.length === 0 ? this.formData.locationName
) : ''
}, },
submitDisableEdit() { locationNameLabelAddOnOldName() {
return this.formLocationName !== '' ? ' — ' + this.formLocationName : ''
},
descriptionLength() {
return this.$filters.removeHtml(this.formData.description).length
},
sameLocation() {
const dbLocationName = this.group.locationName || ''
return dbLocationName === this.formLocationName
},
sameCategories() {
if (this.group.categories.length !== this.formData.categoryIds.length) return false
const groupCategories = []
this.group.categories.forEach((categories) => {
groupCategories.push(categories.id)
const some = this.formData.categoryIds.some((item) => item === categories.id)
if (!some) return false
})
return true
},
disableButtonByUpdate() {
if (!this.update) return true
return ( return (
this.formData.name === this.group.name && this.group.name === this.formData.name &&
this.formData.slug === this.group.slug && this.group.slug === this.formData.slug &&
// this.formData.groupType === this.group.groupType && // can not be changed for now this.group.about === this.formData.about &&
this.formData.about === this.group.about && this.group.description === this.formData.description &&
this.formData.description === this.group.description && this.group.actionRadius === this.formData.actionRadius &&
this.formData.actionRadius === this.group.actionRadius && this.sameLocation &&
this.formData.locationName === (this.group.locationName ? this.group.locationName : '') &&
this.sameCategories this.sameCategories
) )
}, },
sameCategories() {
const formDataCategories = this.formData.categoryIds.map((id) => id).sort()
const groupDataCategories = this.group.categories.map((category) => category.id).sort()
let equal = true
if (formDataCategories.length !== groupDataCategories.length) return false
formDataCategories.forEach((id, index) => {
equal = equal && id === groupDataCategories[index]
})
return equal
},
}, },
methods: { methods: {
checkFormError(error) {
if (!this.update && error && !!error && this.disableButtonByUpdate) return true
if (this.update && !error && this.disableButtonByUpdate) return true
return false
},
changeGroupType(event) {
this.formData.groupType = event.target.value
},
changeActionRadius(event) {
this.formData.actionRadius = event.target.value
},
updateEditorDescription(value) {
this.$refs.groupForm.update('description', value)
},
submit() { submit() {
const { name, about, description, groupType, actionRadius, locationName, categoryIds } = const { name, about, description, groupType, actionRadius, /* locationName, */ categoryIds } =
this.formData this.formData
const variables = { const variables = {
name, name,
@ -246,7 +341,7 @@ export default {
description, description,
groupType, groupType,
actionRadius, actionRadius,
locationName: locationName.label, locationName: this.formLocationName,
categoryIds, categoryIds,
} }
this.update this.update
@ -256,15 +351,12 @@ export default {
}) })
: this.$emit('createGroup', variables) : this.$emit('createGroup', variables)
}, },
changeGroupType(event) { handleCityInput(event) {
this.formData.groupType = event.target.value
},
changeActionRadius(event) {
this.formData.actionRadius = event.target.value
},
handleCityInput(value) {
clearTimeout(timeout) clearTimeout(timeout)
timeout = setTimeout(() => this.requestGeoData(value), 500) timeout = setTimeout(
() => this.requestGeoData(event.target ? event.target.value.trim() : ''),
500,
)
}, },
processLocationsResult(places) { processLocationsResult(places) {
if (!places.length) { if (!places.length) {
@ -281,8 +373,7 @@ export default {
return result return result
}, },
async requestGeoData(e) { async requestGeoData(value) {
const value = e.target ? e.target.value.trim() : ''
if (value === '') { if (value === '') {
this.cities = [] this.cities = []
return return
@ -293,27 +384,57 @@ export default {
const lang = this.$i18n.locale() const lang = this.$i18n.locale()
const { const {
data: { queryLocations: res }, data: { queryLocations: result },
} = await this.$apollo.query({ query: queryLocations(), variables: { place, lang } }) } = await this.$apollo.query({ query: queryLocations(), variables: { place, lang } })
this.cities = this.processLocationsResult(res) this.cities = this.processLocationsResult(result)
this.loadingGeo = false this.loadingGeo = false
return this.cities.find((city) => city.value === value)
}, },
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss">
.appearance--auto {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
}
.select-label { .select-label {
margin-bottom: 3pt; margin-bottom: 0;
color: $text-color-soft; padding-bottom: 4px;
color: #70677e;
font-size: 1rem;
} }
.select-icon {
margin-right: 4pt; .textarea-label {
color: $text-color-disabled; padding-bottom: 14px;
} }
.select {
margin-bottom: $space-small; .group-form {
color: $text-color-base; display: flex;
flex-direction: column;
> .ds-form-item {
margin: 0;
}
> .ds-chip {
align-self: flex-end;
margin: $space-xx-small 0 $space-base;
cursor: default;
}
> .select-field {
align-self: flex-end;
}
> .buttons {
align-self: flex-end;
margin-top: $space-base;
}
} }
</style> </style>

View File

@ -58,7 +58,7 @@
<div v-else class="categories-placeholder"></div> <div v-else class="categories-placeholder"></div>
<!-- group context menu --> <!-- group context menu -->
<client-only> <client-only>
<group-content-menu resource-type="group" :resource="group" :group="group" /> <group-content-menu :usage="'groupTeaser'" :group="group || {}" placement="bottom-end" />
</client-only> </client-only>
</footer> </footer>
<footer class="footer"> <footer class="footer">
@ -78,7 +78,7 @@
<script> <script>
import Category from '~/components/Category' import Category from '~/components/Category'
import GroupContentMenu from '~/components/Group/GroupContentMenu' import GroupContentMenu from '~/components/ContentMenu/GroupContentMenu'
export default { export default {
name: 'GroupTeaser', name: 'GroupTeaser',

View File

@ -6,7 +6,7 @@ const localVue = global.localVue
localVue.filter('date', (d) => d) localVue.filter('date', (d) => d)
config.stubs['client-only'] = '<span><slot /></span>' config.stubs['client-only'] = '<span><slot /></span>'
// config.stubs['v-popover'] = '<span><slot /></span>' config.stubs['v-popover'] = '<span><slot /></span>'
config.stubs['nuxt-link'] = '<span><slot /></span>' config.stubs['nuxt-link'] = '<span><slot /></span>'
// config.stubs['infinite-loading'] = '<span><slot /></span>' // config.stubs['infinite-loading'] = '<span><slot /></span>'
// config.stubs['follow-list'] = '<span><slot /></span>' // config.stubs['follow-list'] = '<span><slot /></span>'
@ -237,6 +237,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(true)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('yoga-practice') expect(wrapper.text()).toContain('yoga-practice')
@ -385,6 +389,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('yoga-practice') expect(wrapper.text()).toContain('yoga-practice')
@ -493,6 +501,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('yoga-practice') expect(wrapper.text()).toContain('yoga-practice')
@ -601,6 +613,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('yoga-practice') expect(wrapper.text()).toContain('yoga-practice')
@ -713,6 +729,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(true)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('school-for-citizens') expect(wrapper.text()).toContain('school-for-citizens')
@ -825,6 +845,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('school-for-citizens') expect(wrapper.text()).toContain('school-for-citizens')
@ -937,6 +961,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('school-for-citizens') expect(wrapper.text()).toContain('school-for-citizens')
@ -1049,6 +1077,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('school-for-citizens') expect(wrapper.text()).toContain('school-for-citizens')
@ -1165,6 +1197,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(true)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('investigative-journalism') expect(wrapper.text()).toContain('investigative-journalism')
@ -1280,6 +1316,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(true) expect(wrapper.find('.profile-avatar').exists()).toBe(true)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has group slug', () => { it('has group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(true) expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
expect(wrapper.text()).toContain('investigative-journalism') expect(wrapper.text()).toContain('investigative-journalism')
@ -1395,6 +1435,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(false) expect(wrapper.find('.profile-avatar').exists()).toBe(false)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has no(!) group slug', () => { it('has no(!) group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(false) expect(wrapper.find('[data-test="at"]').exists()).toBe(false)
expect(wrapper.text()).not.toContain('investigative-journalism') expect(wrapper.text()).not.toContain('investigative-journalism')
@ -1498,6 +1542,10 @@ describe('GroupProfileSlug', () => {
expect(wrapper.find('.profile-avatar').exists()).toBe(false) expect(wrapper.find('.profile-avatar').exists()).toBe(false)
}) })
it('has not(!) GroupContentMenu', () => {
expect(wrapper.find('.group-content-menu').exists()).toBe(false)
})
it('has no(!) group slug', () => { it('has no(!) group slug', () => {
expect(wrapper.find('[data-test="at"]').exists()).toBe(false) expect(wrapper.find('[data-test="at"]').exists()).toBe(false)
expect(wrapper.text()).not.toContain('investigative-journalism') expect(wrapper.text()).not.toContain('investigative-journalism')

View File

@ -16,20 +16,21 @@
</avatar-uploader> </avatar-uploader>
<profile-avatar v-else :profile="group" class="profile-page-avatar" size="large" /> <profile-avatar v-else :profile="group" class="profile-page-avatar" size="large" />
<!-- Menu --> <!-- Menu -->
<!-- <client-only> <client-only>
<content-menu <group-content-menu
v-if="isGroupOwner"
class="group-content-menu"
:usage="'groupProfile'"
:group="group || {}"
placement="bottom-end" placement="bottom-end"
resource-type="user" />
:resource="user" <!-- TODO: implement later on -->
:is-owner="isGroupOwner" <!-- @mute="muteUser"
class="user-content-menu"
@mute="muteUser"
@unmute="unmuteUser" @unmute="unmuteUser"
@block="blockUser" @block="blockUser"
@unblock="unblockUser" @unblock="unblockUser"
@delete="deleteUser" @delete="deleteUser" -->
/> </client-only>
</client-only> -->
<ds-space margin="small"> <ds-space margin="small">
<!-- group name --> <!-- group name -->
<ds-heading tag="h3" align="center" no-margin> <ds-heading tag="h3" align="center" no-margin>
@ -313,12 +314,12 @@ import UpdateQuery from '~/components/utils/UpdateQuery'
import postListActions from '~/mixins/postListActions' import postListActions from '~/mixins/postListActions'
import AvatarUploader from '~/components/Uploader/AvatarUploader' import AvatarUploader from '~/components/Uploader/AvatarUploader'
import Category from '~/components/Category' import Category from '~/components/Category'
// import ContentMenu from '~/components/ContentMenu/ContentMenu'
import ContentViewer from '~/components/Editor/ContentViewer' import ContentViewer from '~/components/Editor/ContentViewer'
import CountTo from '~/components/CountTo.vue' import CountTo from '~/components/CountTo.vue'
import Empty from '~/components/Empty/Empty' import Empty from '~/components/Empty/Empty'
// import FollowButton from '~/components/Button/FollowButton' // import FollowButton from '~/components/Button/FollowButton'
// import FollowList from '~/components/features/ProfileList/FollowList' // import FollowList from '~/components/features/ProfileList/FollowList'
import GroupContentMenu from '~/components/ContentMenu/GroupContentMenu'
import JoinLeaveButton from '~/components/Button/JoinLeaveButton' import JoinLeaveButton from '~/components/Button/JoinLeaveButton'
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue' import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue' import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
@ -340,12 +341,12 @@ export default {
components: { components: {
AvatarUploader, AvatarUploader,
Category, Category,
// ContentMenu,
ContentViewer, ContentViewer,
CountTo, CountTo,
Empty, Empty,
// FollowButton, // FollowButton,
// FollowList, // FollowList,
GroupContentMenu,
JoinLeaveButton, JoinLeaveButton,
PostTeaser, PostTeaser,
ProfileAvatar, ProfileAvatar,
@ -634,8 +635,8 @@ export default {
margin: auto; margin: auto;
margin-top: -60px; margin-top: -60px;
} }
.page-name-profile-id-slug { .page-name-group-id-slug {
.ds-flex-item:first-child .content-menu { .ds-flex-item:first-child .group-content-menu {
position: absolute; position: absolute;
top: $space-x-small; top: $space-x-small;
right: $space-x-small; right: $space-x-small;

View File

@ -22,11 +22,6 @@ export default {
required: true, required: true,
}, },
}, },
data() {
return {
GroupMembers: [],
}
},
computed: { computed: {
groupMembers() { groupMembers() {
return this.GroupMembers ? this.GroupMembers : [] return this.GroupMembers ? this.GroupMembers : []