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-21 11:34:31 +02:00
commit 9773a7b4ba
19 changed files with 237 additions and 65 deletions

View File

@ -1,3 +1,5 @@
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!--
Please take a look at the issue templates at https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/new/choose
before submitting a new issue. Following one of the issue templates will ensure maintainers can route your request efficiently.

View File

@ -1,11 +1,10 @@
---
name: "\U0001F41B Bug Report"
about: Create a report to help us to improve.
title: "\U0001F41B [Bug] XXX"
name: 🐛 Bug report
about: Create a report to help us improve
labels: bug
assignees: ''
title: 🐛 [Bug]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## :bug: Bug Report
## 🐛 Bugreport
<!-- Describe your issue in detail. Include screenshots if needed. Give us as much information as possible. Use a clear and concise description of what the bug is.-->

View File

@ -1,11 +1,10 @@
---
name: "\U0001F4A5 DevOps Ticket"
about: Help us manage our deployed app.
title: "\U0001F4A5 [DevOps] XXX"
name: 💥 DevOps ticket
about: Help us manage our deployed Software.
labels: devops
assignees: ''
title: 💥 [DevOps]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 💥 DevOps Ticket
## 💥 DevOps ticket
<!-- Describe your issue in detail. Include screenshots if needed. Give us as much information as possible. Use a clear and concise description of what the problem is.-->

View File

@ -1,15 +1,13 @@
---
name: "\U0001F31F Epic"
about: Define a big development step.
title: "\U0001F31F [EPIC] XXX"
name: 🌟 Epic
about: Define a big development Step
labels: epic
assignees: ''
title: 🌟 [EPIC]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!-- THIS ISSUE-TYPE IS NOT FOR YOU! -->
<!-- If you need an answer right away, visit the ocelot.social Discord:
https://discord.gg/AJSX9DCSUA -->
<!-- Proceed only if you know what you are doing - have a chat with Project's Team first -->
## 🌟 EPIC
<!-- Describe your Epic in detail. Include screenshots and drawings -->

View File

@ -1,11 +1,10 @@
---
name: "\U0001F680 Feature Request"
about: Suggest an idea for this project.
title: "\U0001F680 [Feature] XXX"
name: 🚀 Feature request
about: Suggest an idea for this project
labels: feature
assignees: ''
title: 🚀 [Feature]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## :rocket: Feature Request
## 🚀 Feature
<!-- Give a short summary of the Feature. Use Screenshots if you want. -->

View File

@ -1,15 +1,13 @@
---
name: "\U0001F4AC Question"
about: If you need help understanding ocelot.social.
title: "\U0001F4AC [Question] XXX"
name: 💬 Question
about: If you need help understanding our Software.
labels: question
assignees: ''
title: 💬 [Question]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!-- Chat with ocelot.social team -->
<!-- If you need an answer right away, visit the ocelot.social Discord:
https://discord.gg/AJSX9DCSUA -->
<!-- Question the project's team -->
<!-- If you need an answer right away, consider to take other means of communication with the project's team -->
## 💬 Question
<!-- Describe your Question in detail. Include screenshots and drawings if needed. -->

View File

@ -1,11 +1,10 @@
---
name: "\U0001F527 Refactor"
name: 🔧 Refactor ticket
about: Help us improve our code by refactoring it.
title: "\U0001F527 [Refactor] XXX"
labels: refactor
assignees: ''
title: 🔧 [Refactor]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 🔧 Refactor
## 🔧 Refactor ticket
<!-- Describe your issue in detail. Include screenshots if needed. Give us as much information as possible. Use a clear and concise description of what the problem is.-->

13
.github/ISSUE_TEMPLATE/release.md vendored Normal file
View File

@ -0,0 +1,13 @@
---
name: 🎂 Release
about: Define a Release
labels: release
title: 🎂 [RELEASE]
---
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
<!-- THIS ISSUE-TYPE IS NOT FOR YOU! -->
<!-- Proceed only if you know what you are doing - have a chat with Project's Team first -->
## 🎂 RELEASE
<!-- Describe your Release in detail. Include screenshots and drawings -->

View File

@ -1,15 +1,15 @@
## 🍰 Pull Request
<!-- You can find the latest issue templates here https://github.com/ulfgebhardt/issue-templates -->
## 🍰 Pullrequest
<!-- Describe the Pullrequest. Use Screenshots if possible. -->
XXX
### Issues
<!-- Which Issues does this fix, which are related? -->
<!-- Which Issues does this fix, which are related?
- fixes #XXX
- relates #XXX
-->
- None
### Todo
<!-- In case some parts are still missing, list them here. -->
- [ ] XXX list here …
- [X] None

View File

@ -14,6 +14,7 @@
<div class="filter-menu-options">
<h2 class="title">{{ $t('filter-menu.filter-by') }}</h2>
<following-filter />
<categories-filter v-if="categoriesActive" />
</div>
<div class="filter-menu-options">
<h2 class="title">{{ $t('filter-menu.order-by') }}</h2>
@ -28,12 +29,19 @@ import Dropdown from '~/components/Dropdown'
import { mapGetters } from 'vuex'
import FollowingFilter from './FollowingFilter'
import OrderByFilter from './OrderByFilter'
import CategoriesFilter from './CategoriesFilter'
export default {
components: {
Dropdown,
FollowingFilter,
OrderByFilter,
CategoriesFilter,
},
data() {
return {
categoriesActive: this.$env.CATEGORIES_ACTIVE,
}
},
props: {
placement: { type: String },

View File

@ -0,0 +1,33 @@
import { mount } from '@vue/test-utils'
import GroupList from './GroupList.vue'
const localVue = global.localVue
const propsData = {
groups: [],
}
describe('GroupList', () => {
let wrapper
let mocks
beforeEach(() => {
mocks = {
$t: jest.fn(),
}
})
describe('mount', () => {
const Wrapper = () => {
return mount(GroupList, { propsData, mocks, localVue })
}
beforeEach(() => {
wrapper = Wrapper()
})
it('renders', () => {
expect(wrapper.findAll('.group-list')).toHaveLength(1)
})
})
})

View File

@ -1,5 +1,5 @@
<template>
<div>
<div class="group-list">
<ds-space margin-bottom="small" v-for="group in groups" :key="group.id">
<group-teaser :group="group" />
</ds-space>

View File

@ -0,0 +1,34 @@
import { mount } from '@vue/test-utils'
import GroupMember from './GroupMember.vue'
const localVue = global.localVue
const propsData = {
groupId: '',
groupMembers: [],
}
describe('GroupMember', () => {
let wrapper
let mocks
beforeEach(() => {
mocks = {
$t: jest.fn(),
}
})
describe('mount', () => {
const Wrapper = () => {
return mount(GroupMember, { propsData, mocks, localVue })
}
beforeEach(() => {
wrapper = Wrapper()
})
it('renders', () => {
expect(wrapper.findAll('.group-member')).toHaveLength(1)
})
})
})

View File

@ -1,5 +1,41 @@
<template>
<div>
<div class="group-member">
<base-card>
<h2 class="title">{{ $t('group.addUser') }}</h2>
<ds-form v-model="form" @submit="submit">
<ds-flex gutter="small">
<ds-flex-item width="90%">
<ds-input
name="query"
model="query"
:placeholder="$t('group.addUserPlaceholder')"
icon="search"
/>
</ds-flex-item>
<ds-flex-item width="30px">
<!-- <base-button filled circle type="submit" icon="search" :loading="$apollo.loading" /> -->
<base-button filled circle type="submit" icon="search" />
</ds-flex-item>
</ds-flex>
</ds-form>
<div v-if="noSlug">Kein User mit diesem Slug gefunden!</div>
<div v-if="slugUser.length > 0">
<ds-space margin="base" />
<ds-flex>
<ds-flex-item>
<ds-avatar online size="small" :name="slugUser[0].name"></ds-avatar>
</ds-flex-item>
<ds-flex-item>{{ slugUser[0].name }}</ds-flex-item>
<ds-flex-item>{{ slugUser[0].slug }}</ds-flex-item>
<ds-flex-item>
<ds-button size="small" primary @click="addMemberToGroup(slugUser)">
{{ $t('group.addMemberToGroup') }}
</ds-button>
</ds-flex-item>
</ds-flex>
<ds-space margin="base" />
</div>
</base-card>
<ds-table :fields="tableFields" :data="groupMembers" condensed>
<template #avatar="scope">
<nuxt-link
@ -51,7 +87,12 @@
</ds-chip>
</template>
<template #edit="scope">
<ds-button size="small" primary :disabled="true" @click="openModal(scope.row)">
<ds-button
v-if="scope.row.myRoleInGroup !== 'owner'"
size="small"
primary
@click="deleteMember(scope.row.id)"
>
<!-- TODO: implement removal of group members -->
<!-- :disabled="scope.row.myRoleInGroup === 'owner'"
-->
@ -74,6 +115,7 @@
</div>
</template>
<script>
import { minimisedUserQuery } from '~/graphql/User'
import { changeGroupMemberRoleMutation } from '~/graphql/groups.js'
export default {
@ -92,6 +134,11 @@ export default {
return {
isOpen: false,
memberId: null,
noSlug: false,
slugUser: [],
form: {
query: '',
},
}
},
computed: {
@ -135,14 +182,53 @@ export default {
this.$toast.error(error.message)
}
},
async addMemberToGroup() {
const newRole = 'usual'
try {
await this.$apollo.mutate({
mutation: changeGroupMemberRoleMutation(),
variables: { groupId: this.groupId, userId: this.slugUser[0].id, roleInGroup: newRole },
})
// this.$apollo.queries.GroupMembers.refetch()
this.$emit('loadGroupMembers')
this.slugUser = []
this.form.query = ''
this.$toast.success(
this.$t('group.changeMemberRole', { role: this.$t(`group.roles.${newRole}`) }),
)
} catch (error) {
this.$toast.error(error.message)
}
},
async submit() {
try {
const {
data: { User },
} = await this.$apollo.query({
query: minimisedUserQuery(),
variables: {
slug: this.form.query,
},
})
if (User.length === 0) {
this.noSlug = true
} else {
this.noSlug = false
this.slugUser = User
}
} catch (error) {
this.noSlug = true
} finally {
}
},
// TODO: implement removal of group members
// openModal(row) {
// this.isOpen = true
// this.memberId = row.id
// },
// deleteMember(id) {
// alert('deleteMember: ' + id)
// },
deleteMember(id) {
alert('deleteMember: ' + id)
},
},
}
</script>

View File

@ -49,8 +49,8 @@ export default (i18n) => {
export const minimisedUserQuery = () => {
return gql`
query {
User(orderBy: slug_asc) {
query ($slug: String) {
User(slug: $slug, orderBy: slug_asc) {
id
slug
name

View File

@ -28,15 +28,6 @@
</ds-text>
</nuxt-link>
</ds-flex-item>
<ds-flex-item
v-if="categoriesActive && isLoggedIn"
:class="{ 'hide-mobile-menu': !toggleMobileMenu }"
style="flex-grow: 0; flex-basis: auto; margin-right: 20px"
>
<client-only>
<categories-menu></categories-menu>
</client-only>
</ds-flex-item>
<ds-flex-item
:width="{ base: '40%', sm: '40%', md: '40%', lg: '0%' }"
class="mobile-hamburger-menu"
@ -125,7 +116,6 @@ import LocaleSwitch from '~/components/LocaleSwitch/LocaleSwitch'
import SearchField from '~/components/features/SearchField/SearchField.vue'
import Modal from '~/components/Modal'
import AvatarMenu from '~/components/AvatarMenu/AvatarMenu'
import CategoriesMenu from '~/components/FilterMenu/CategoriesMenu'
import FilterMenu from '~/components/FilterMenu/FilterMenu.vue'
import GroupButton from '~/components/Group/GroupButton'
import InviteButton from '~/components/InviteButton/InviteButton'
@ -143,7 +133,6 @@ export default {
FilterMenu,
PageFooter,
InviteButton,
CategoriesMenu,
GroupButton,
},
mixins: [seo],

View File

@ -404,6 +404,9 @@
"regional": "Regionale Gruppe"
},
"actionRadius": "Aktionsradius",
"addMemberToGroup": "Zur Gruppe hinzufügen",
"addUser": "Benutzer hinzufügen",
"addUserPlaceholder": "eindeutiger Benutzername > @slug-from-user",
"categories": "Thema ::: Themen",
"changeMemberRole": "Die Rolle wurde auf „{role}“ geändert!",
"contentMenu": {

View File

@ -404,6 +404,9 @@
"regional": "Regional Group"
},
"actionRadius": "Action radius",
"addMemberToGroup": "Add to group",
"addUser": "Add User",
"addUserPlaceholder": "unique username > @slug-from-user",
"categories": "Topic ::: Topics",
"changeMemberRole": "The role has been changed to “{role}”!",
"contentMenu": {

View File

@ -3,7 +3,11 @@
<base-card>
<ds-heading tag="h3">{{ $t('group.members') }}</ds-heading>
<ds-space margin="large" />
<group-member :groupId="group.id" :groupMembers="groupMembers" />
<group-member
:groupId="group.id"
:groupMembers="groupMembers"
@loadGroupMembers="loadGroupMembers"
/>
</base-card>
</div>
</template>
@ -44,5 +48,10 @@ export default {
fetchPolicy: 'cache-and-network',
},
},
methods: {
loadGroupMembers() {
this.$apollo.queries.GroupMembers.refetch()
},
},
}
</script>