mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
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:
commit
2eb5995116
@ -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()
|
||||
await Promise.all([
|
||||
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()
|
||||
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
|
||||
|
||||
const [p0, p1, p3, p4, p5, p6, p9, p10, p11, p13, p14, p15] = await Promise.all([
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
icon="ellipsis-v"
|
||||
size="small"
|
||||
circle
|
||||
ghost
|
||||
@click.prevent="toggleMenu()"
|
||||
/>
|
||||
</slot>
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { config, mount } from '@vue/test-utils'
|
||||
import GroupContentMenu from './GroupContentMenu.vue'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
config.stubs['router-link'] = '<span><slot /></span>'
|
||||
|
||||
const propsData = {
|
||||
usage: 'groupTeaser',
|
||||
resource: {},
|
||||
group: {},
|
||||
resourceType: 'group',
|
||||
@ -29,7 +32,7 @@ describe('GroupContentMenu', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.findAll('.group-menu')).toHaveLength(1)
|
||||
expect(wrapper.findAll('.group-content-menu')).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<dropdown class="group-menu" :placement="placement" offset="5">
|
||||
<dropdown class="group-content-menu" :placement="placement" offset="5">
|
||||
<template #default="{ toggleMenu }">
|
||||
<slot name="button" :toggleMenu="toggleMenu">
|
||||
<base-button
|
||||
@ -40,35 +40,34 @@ export default {
|
||||
Dropdown,
|
||||
},
|
||||
props: {
|
||||
placement: { type: String, default: 'bottom-end' },
|
||||
resource: { type: Object, required: true },
|
||||
group: { type: Object, required: true },
|
||||
resourceType: {
|
||||
usage: {
|
||||
type: String,
|
||||
required: true,
|
||||
validator: (value) => {
|
||||
return value.match(/(group)/)
|
||||
return value.match(/(groupTeaser|groupProfile)/)
|
||||
},
|
||||
},
|
||||
group: { type: Object, required: true },
|
||||
placement: { type: String, default: 'bottom-end' },
|
||||
},
|
||||
computed: {
|
||||
routes() {
|
||||
const routes = []
|
||||
|
||||
if (this.resourceType === 'group') {
|
||||
if (this.usage !== 'groupProfile') {
|
||||
routes.push({
|
||||
label: this.$t('group.contentMenu.visitGroupPage'),
|
||||
icon: 'home',
|
||||
name: 'group-id-slug',
|
||||
params: { id: this.group.id, slug: this.group.slug },
|
||||
})
|
||||
if (this.group.myRole === 'owner') {
|
||||
routes.push({
|
||||
label: this.$t('admin.settings.name'),
|
||||
path: `/group/edit/${this.resource.id}`,
|
||||
icon: 'edit',
|
||||
})
|
||||
}
|
||||
}
|
||||
if (this.group.myRole === 'owner') {
|
||||
routes.push({
|
||||
label: this.$t('admin.settings.name'),
|
||||
path: `/group/edit/${this.group.id}`,
|
||||
icon: 'edit',
|
||||
})
|
||||
}
|
||||
|
||||
return routes
|
||||
@ -7,79 +7,97 @@
|
||||
:schema="formSchema"
|
||||
@submit="submit"
|
||||
>
|
||||
<ds-input
|
||||
:label="$t('group.name')"
|
||||
v-model="formData.name"
|
||||
:placeholder="`${$t('group.name')} …`"
|
||||
></ds-input>
|
||||
<ds-input
|
||||
v-if="update"
|
||||
:label="$t('group.labelSlug')"
|
||||
v-model="formData.slug"
|
||||
icon="at"
|
||||
:placeholder="`${$t('group.labelSlug')} …`"
|
||||
></ds-input>
|
||||
<!-- groupType -->
|
||||
<!-- TODO: change it has to be implemented later -->
|
||||
<!-- TODO: move 'ds-select' from styleguide to main code and implement missen translation etc. functionality -->
|
||||
<!-- <ds-select
|
||||
id="groupType"
|
||||
:label="$t('group.type')"
|
||||
:v-model="formData.groupType"
|
||||
:label-prop="'label'"
|
||||
:options="groupTypeOptions"
|
||||
icon="user"
|
||||
:placeholder="$t('group.type') + ' …'"
|
||||
></ds-select> -->
|
||||
<ds-text class="select-label">
|
||||
{{ $t('group.type') }}
|
||||
</ds-text>
|
||||
<ds-icon class="select-icon" name="user" />
|
||||
<select
|
||||
class="select"
|
||||
:options="groupTypeOptions"
|
||||
:value="formData.groupType"
|
||||
:disabled="update"
|
||||
@change="changeGroupType($event)"
|
||||
>
|
||||
<option v-for="groupType in groupTypeOptions" :key="groupType" :value="groupType">
|
||||
{{ $t(`group.types.${groupType}`) }}
|
||||
</option>
|
||||
</select>
|
||||
<!-- goal -->
|
||||
<ds-input
|
||||
:label="$t('group.goal')"
|
||||
v-model="formData.about"
|
||||
:placeholder="$t('group.goal') + ' …'"
|
||||
rows="3"
|
||||
></ds-input>
|
||||
<!-- description -->
|
||||
<ds-input
|
||||
:label="$t('group.description')"
|
||||
v-model="formData.description"
|
||||
:placeholder="$t('group.description') + ' …'"
|
||||
type="textarea"
|
||||
rows="3"
|
||||
></ds-input>
|
||||
<ds-space margin-top="large">
|
||||
<!-- "errors" is only working if you use a submit event on the form -->
|
||||
<template #default="{ errors }">
|
||||
<!-- group Name -->
|
||||
<ds-input
|
||||
name="name"
|
||||
:label="$t('group.name')"
|
||||
model="name"
|
||||
autofocus
|
||||
:placeholder="`${$t('group.name')} …`"
|
||||
/>
|
||||
<ds-chip size="base" :color="errors && errors.name ? 'danger' : 'medium'">
|
||||
{{ `${formData.name.length} / ${formSchema.name.min}–${formSchema.name.max}` }}
|
||||
<base-icon v-if="errors && errors.name" name="warning" />
|
||||
</ds-chip>
|
||||
|
||||
<!-- group Slug -->
|
||||
<ds-input
|
||||
v-if="update"
|
||||
:label="$t('group.labelSlug')"
|
||||
model="slug"
|
||||
icon="at"
|
||||
:placeholder="`${$t('group.labelSlug')} …`"
|
||||
></ds-input>
|
||||
|
||||
<ds-space v-if="update" margin-top="small" />
|
||||
|
||||
<!-- groupType -->
|
||||
<ds-text class="select-label">
|
||||
{{ $t('group.type') }}
|
||||
</ds-text>
|
||||
<!-- TODO: change it has to be implemented later -->
|
||||
<!-- TODO: move 'ds-select' from style guide to main code and implement missing translation etc. functionality -->
|
||||
<select
|
||||
class="select ds-input appearance--auto"
|
||||
name="groupType"
|
||||
model="groupType"
|
||||
:value="formData.groupType"
|
||||
:disabled="update"
|
||||
@change="changeGroupType($event)"
|
||||
>
|
||||
<option v-for="groupType in groupTypeOptions" :key="groupType" :value="groupType">
|
||||
{{ $t(`group.types.${groupType}`) }}
|
||||
</option>
|
||||
</select>
|
||||
<ds-chip
|
||||
size="base"
|
||||
:color="errors && errors.groupType && formData.groupType === '' ? 'danger' : 'medium'"
|
||||
>
|
||||
{{ `${formData.groupType === '' ? 0 : 1} / 1` }}
|
||||
<base-icon
|
||||
v-if="errors && errors.groupType && formData.groupType === ''"
|
||||
name="warning"
|
||||
/>
|
||||
</ds-chip>
|
||||
|
||||
<!-- 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 -->
|
||||
<!-- 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">
|
||||
{{ $t('group.actionRadius') }}
|
||||
</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
|
||||
class="select"
|
||||
:options="actionRadiusOptions"
|
||||
class="select ds-input appearance--auto"
|
||||
name="actionRadius"
|
||||
:value="formData.actionRadius"
|
||||
@change="changeActionRadius($event)"
|
||||
>
|
||||
@ -91,41 +109,68 @@
|
||||
{{ $t(`group.actionRadii.${actionRadius}`) }}
|
||||
</option>
|
||||
</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 -->
|
||||
<ds-select
|
||||
id="city"
|
||||
:label="$t('settings.data.labelCity')"
|
||||
:label="$t('settings.data.labelCity') + locationNameLabelAddOnOldName"
|
||||
v-model="formData.locationName"
|
||||
:options="cities"
|
||||
icon="map-marker"
|
||||
:icon-right="null"
|
||||
:placeholder="$t('settings.data.labelCity') + ' …'"
|
||||
:loading="loadingGeo"
|
||||
@input.native="handleCityInput"
|
||||
/>
|
||||
<!-- TODO: implement clear button -->
|
||||
<!-- <base-button icon="close" circle ghost size="small" :disabled="formData.locationName.length === 0" @click="clear" /> -->
|
||||
</ds-space>
|
||||
<ds-space margin-top="large">
|
||||
<base-button
|
||||
v-if="formLocationName !== ''"
|
||||
icon="close"
|
||||
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
|
||||
v-if="categoriesActive"
|
||||
model="categoryIds"
|
||||
name="categoryIds"
|
||||
:existingCategoryIds="formData.categoryIds"
|
||||
/>
|
||||
</ds-space>
|
||||
<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"
|
||||
:disabled="update ? submitDisableEdit : submitDisable"
|
||||
primary
|
||||
@click.prevent="submit()"
|
||||
<ds-chip
|
||||
v-if="categoriesActive"
|
||||
size="base"
|
||||
:color="errors && errors.categoryIds ? 'danger' : 'medium'"
|
||||
>
|
||||
{{ update ? $t('group.update') : $t('group.save') }}
|
||||
</ds-button>
|
||||
</ds-space>
|
||||
{{ formData.categoryIds.length }} / 3
|
||||
<base-icon v-if="errors && errors.categoryIds" name="warning" />
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
@ -133,7 +178,12 @@
|
||||
<script>
|
||||
import CategoriesSelect from '~/components/CategoriesSelect/CategoriesSelect'
|
||||
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'
|
||||
|
||||
let timeout
|
||||
@ -142,6 +192,7 @@ export default {
|
||||
name: 'GroupForm',
|
||||
components: {
|
||||
CategoriesSelect,
|
||||
Editor,
|
||||
},
|
||||
props: {
|
||||
update: {
|
||||
@ -171,17 +222,33 @@ export default {
|
||||
groupType: groupType || '',
|
||||
about: about || '',
|
||||
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 || '',
|
||||
actionRadius: actionRadius || '',
|
||||
categoryIds: categories ? categories.map((category) => category.id) : [],
|
||||
},
|
||||
formSchema: {
|
||||
name: { required: true, min: NAME_LENGTH_MIN, max: NAME_LENGTH_MAX },
|
||||
slug: { required: false },
|
||||
groupType: { required: true },
|
||||
about: { required: true },
|
||||
description: { required: true },
|
||||
actionRadius: { required: true },
|
||||
slug: { required: false, min: NAME_LENGTH_MIN },
|
||||
groupType: { required: true, min: 1 },
|
||||
about: { required: false },
|
||||
description: {
|
||||
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 },
|
||||
categoryIds: {
|
||||
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: {
|
||||
submitDisable() {
|
||||
return (
|
||||
this.formData.name === '' ||
|
||||
this.formData.groupType === '' ||
|
||||
// this.formData.about === '' || // not mandatory
|
||||
this.formData.description === '' ||
|
||||
this.formData.actionRadius === '' ||
|
||||
// this.formData.locationName === '' || // not mandatory
|
||||
this.formData.categoryIds.length === 0
|
||||
)
|
||||
formLocationName() {
|
||||
const isNestedValue =
|
||||
typeof this.formData.locationName === 'object' &&
|
||||
typeof this.formData.locationName.value === 'string'
|
||||
const isDirectString = typeof this.formData.locationName === 'string'
|
||||
return isNestedValue
|
||||
? this.formData.locationName.value
|
||||
: isDirectString
|
||||
? 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 (
|
||||
this.formData.name === this.group.name &&
|
||||
this.formData.slug === this.group.slug &&
|
||||
// this.formData.groupType === this.group.groupType && // can not be changed for now
|
||||
this.formData.about === this.group.about &&
|
||||
this.formData.description === this.group.description &&
|
||||
this.formData.actionRadius === this.group.actionRadius &&
|
||||
this.formData.locationName === (this.group.locationName ? this.group.locationName : '') &&
|
||||
this.group.name === this.formData.name &&
|
||||
this.group.slug === this.formData.slug &&
|
||||
this.group.about === this.formData.about &&
|
||||
this.group.description === this.formData.description &&
|
||||
this.group.actionRadius === this.formData.actionRadius &&
|
||||
this.sameLocation &&
|
||||
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: {
|
||||
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() {
|
||||
const { name, about, description, groupType, actionRadius, locationName, categoryIds } =
|
||||
const { name, about, description, groupType, actionRadius, /* locationName, */ categoryIds } =
|
||||
this.formData
|
||||
const variables = {
|
||||
name,
|
||||
@ -246,7 +341,7 @@ export default {
|
||||
description,
|
||||
groupType,
|
||||
actionRadius,
|
||||
locationName: locationName.label,
|
||||
locationName: this.formLocationName,
|
||||
categoryIds,
|
||||
}
|
||||
this.update
|
||||
@ -256,15 +351,12 @@ export default {
|
||||
})
|
||||
: this.$emit('createGroup', variables)
|
||||
},
|
||||
changeGroupType(event) {
|
||||
this.formData.groupType = event.target.value
|
||||
},
|
||||
changeActionRadius(event) {
|
||||
this.formData.actionRadius = event.target.value
|
||||
},
|
||||
handleCityInput(value) {
|
||||
handleCityInput(event) {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => this.requestGeoData(value), 500)
|
||||
timeout = setTimeout(
|
||||
() => this.requestGeoData(event.target ? event.target.value.trim() : ''),
|
||||
500,
|
||||
)
|
||||
},
|
||||
processLocationsResult(places) {
|
||||
if (!places.length) {
|
||||
@ -281,8 +373,7 @@ export default {
|
||||
|
||||
return result
|
||||
},
|
||||
async requestGeoData(e) {
|
||||
const value = e.target ? e.target.value.trim() : ''
|
||||
async requestGeoData(value) {
|
||||
if (value === '') {
|
||||
this.cities = []
|
||||
return
|
||||
@ -293,27 +384,57 @@ export default {
|
||||
const lang = this.$i18n.locale()
|
||||
|
||||
const {
|
||||
data: { queryLocations: res },
|
||||
data: { queryLocations: result },
|
||||
} = await this.$apollo.query({ query: queryLocations(), variables: { place, lang } })
|
||||
|
||||
this.cities = this.processLocationsResult(res)
|
||||
this.cities = this.processLocationsResult(result)
|
||||
this.loadingGeo = false
|
||||
|
||||
return this.cities.find((city) => city.value === value)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
<style lang="scss">
|
||||
.appearance--auto {
|
||||
-webkit-appearance: auto;
|
||||
-moz-appearance: auto;
|
||||
appearance: auto;
|
||||
}
|
||||
|
||||
.select-label {
|
||||
margin-bottom: 3pt;
|
||||
color: $text-color-soft;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 4px;
|
||||
color: #70677e;
|
||||
font-size: 1rem;
|
||||
}
|
||||
.select-icon {
|
||||
margin-right: 4pt;
|
||||
color: $text-color-disabled;
|
||||
|
||||
.textarea-label {
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
.select {
|
||||
margin-bottom: $space-small;
|
||||
color: $text-color-base;
|
||||
|
||||
.group-form {
|
||||
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>
|
||||
|
||||
@ -58,7 +58,7 @@
|
||||
<div v-else class="categories-placeholder"></div>
|
||||
<!-- group context menu -->
|
||||
<client-only>
|
||||
<group-content-menu resource-type="group" :resource="group" :group="group" />
|
||||
<group-content-menu :usage="'groupTeaser'" :group="group || {}" placement="bottom-end" />
|
||||
</client-only>
|
||||
</footer>
|
||||
<footer class="footer">
|
||||
@ -78,7 +78,7 @@
|
||||
|
||||
<script>
|
||||
import Category from '~/components/Category'
|
||||
import GroupContentMenu from '~/components/Group/GroupContentMenu'
|
||||
import GroupContentMenu from '~/components/ContentMenu/GroupContentMenu'
|
||||
|
||||
export default {
|
||||
name: 'GroupTeaser',
|
||||
|
||||
@ -6,7 +6,7 @@ const localVue = global.localVue
|
||||
localVue.filter('date', (d) => d)
|
||||
|
||||
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['infinite-loading'] = '<span><slot /></span>'
|
||||
// config.stubs['follow-list'] = '<span><slot /></span>'
|
||||
@ -237,6 +237,10 @@ describe('GroupProfileSlug', () => {
|
||||
expect(wrapper.find('.profile-avatar').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has GroupContentMenu', () => {
|
||||
expect(wrapper.find('.group-content-menu').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has group slug', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('yoga-practice')
|
||||
@ -385,6 +389,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('yoga-practice')
|
||||
@ -493,6 +501,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('yoga-practice')
|
||||
@ -601,6 +613,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('yoga-practice')
|
||||
@ -713,6 +729,10 @@ describe('GroupProfileSlug', () => {
|
||||
expect(wrapper.find('.profile-avatar').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has GroupContentMenu', () => {
|
||||
expect(wrapper.find('.group-content-menu').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has group slug', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('school-for-citizens')
|
||||
@ -825,6 +845,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('school-for-citizens')
|
||||
@ -937,6 +961,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('school-for-citizens')
|
||||
@ -1049,6 +1077,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('school-for-citizens')
|
||||
@ -1165,6 +1197,10 @@ describe('GroupProfileSlug', () => {
|
||||
expect(wrapper.find('.profile-avatar').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has GroupContentMenu', () => {
|
||||
expect(wrapper.find('.group-content-menu').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('has group slug', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('investigative-journalism')
|
||||
@ -1280,6 +1316,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(true)
|
||||
expect(wrapper.text()).toContain('investigative-journalism')
|
||||
@ -1395,6 +1435,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(false)
|
||||
expect(wrapper.text()).not.toContain('investigative-journalism')
|
||||
@ -1498,6 +1542,10 @@ describe('GroupProfileSlug', () => {
|
||||
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', () => {
|
||||
expect(wrapper.find('[data-test="at"]').exists()).toBe(false)
|
||||
expect(wrapper.text()).not.toContain('investigative-journalism')
|
||||
|
||||
@ -16,20 +16,21 @@
|
||||
</avatar-uploader>
|
||||
<profile-avatar v-else :profile="group" class="profile-page-avatar" size="large" />
|
||||
<!-- Menu -->
|
||||
<!-- <client-only>
|
||||
<content-menu
|
||||
<client-only>
|
||||
<group-content-menu
|
||||
v-if="isGroupOwner"
|
||||
class="group-content-menu"
|
||||
:usage="'groupProfile'"
|
||||
:group="group || {}"
|
||||
placement="bottom-end"
|
||||
resource-type="user"
|
||||
:resource="user"
|
||||
:is-owner="isGroupOwner"
|
||||
class="user-content-menu"
|
||||
@mute="muteUser"
|
||||
/>
|
||||
<!-- TODO: implement later on -->
|
||||
<!-- @mute="muteUser"
|
||||
@unmute="unmuteUser"
|
||||
@block="blockUser"
|
||||
@unblock="unblockUser"
|
||||
@delete="deleteUser"
|
||||
/>
|
||||
</client-only> -->
|
||||
@delete="deleteUser" -->
|
||||
</client-only>
|
||||
<ds-space margin="small">
|
||||
<!-- group name -->
|
||||
<ds-heading tag="h3" align="center" no-margin>
|
||||
@ -313,12 +314,12 @@ import UpdateQuery from '~/components/utils/UpdateQuery'
|
||||
import postListActions from '~/mixins/postListActions'
|
||||
import AvatarUploader from '~/components/Uploader/AvatarUploader'
|
||||
import Category from '~/components/Category'
|
||||
// import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
||||
import ContentViewer from '~/components/Editor/ContentViewer'
|
||||
import CountTo from '~/components/CountTo.vue'
|
||||
import Empty from '~/components/Empty/Empty'
|
||||
// import FollowButton from '~/components/Button/FollowButton'
|
||||
// import FollowList from '~/components/features/ProfileList/FollowList'
|
||||
import GroupContentMenu from '~/components/ContentMenu/GroupContentMenu'
|
||||
import JoinLeaveButton from '~/components/Button/JoinLeaveButton'
|
||||
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
|
||||
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
|
||||
@ -340,12 +341,12 @@ export default {
|
||||
components: {
|
||||
AvatarUploader,
|
||||
Category,
|
||||
// ContentMenu,
|
||||
ContentViewer,
|
||||
CountTo,
|
||||
Empty,
|
||||
// FollowButton,
|
||||
// FollowList,
|
||||
GroupContentMenu,
|
||||
JoinLeaveButton,
|
||||
PostTeaser,
|
||||
ProfileAvatar,
|
||||
@ -634,8 +635,8 @@ export default {
|
||||
margin: auto;
|
||||
margin-top: -60px;
|
||||
}
|
||||
.page-name-profile-id-slug {
|
||||
.ds-flex-item:first-child .content-menu {
|
||||
.page-name-group-id-slug {
|
||||
.ds-flex-item:first-child .group-content-menu {
|
||||
position: absolute;
|
||||
top: $space-x-small;
|
||||
right: $space-x-small;
|
||||
|
||||
@ -22,11 +22,6 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
GroupMembers: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
groupMembers() {
|
||||
return this.GroupMembers ? this.GroupMembers : []
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user