mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge branch 'master' into 6339-bug-webapp-event-update-page
This commit is contained in:
commit
3cd55051f7
@ -12,7 +12,6 @@ docker-compose*.yml
|
||||
./*.log
|
||||
|
||||
node_modules/
|
||||
scripts/
|
||||
build/
|
||||
|
||||
maintenance-worker/
|
||||
|
||||
@ -74,7 +74,7 @@ FROM code as build
|
||||
# yarn install
|
||||
RUN yarn install --production=false --frozen-lockfile --non-interactive
|
||||
# yarn build
|
||||
RUN yarn run build
|
||||
RUN /bin/sh -c "yarn run build"
|
||||
|
||||
##################################################################################
|
||||
# TEST ###########################################################################
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
"__migrate": "migrate --compiler 'js:@babel/register' --migrations-dir ./src/db/migrations",
|
||||
"prod:migrate": "migrate --migrations-dir ./build/db/migrations --store ./build/db/migrate/store.js",
|
||||
"start": "node build/",
|
||||
"build": "tsc && mkdir -p build/middleware/helpers/email/templates/ && cp -r src/middleware/helpers/email/templates/*.html build/middleware/helpers/email/templates/ && mkdir -p build/middleware/helpers/email/templates/en/ && cp -r src/middleware/helpers/email/templates/en/*.html build/middleware/helpers/email/templates/en/ && mkdir -p build/middleware/helpers/email/templates/de/ && cp -r src/middleware/helpers/email/templates/de/*.html build/middleware/helpers/email/templates/de/ && mkdir -p build/schema/types/ && cp -r src/schema/types/*.gql build/schema/types/ && mkdir -p build/schema/types/enum/ && cp -r src/schema/types/enum/*.gql build/schema/types/enum/ && mkdir -p build/schema/types/scalar/ && cp -r src/schema/types/scalar/*.gql build/schema/types/scalar/ && mkdir -p build/schema/types/type/ && cp -r src/schema/types/type/*.gql build/schema/types/type/",
|
||||
"build": "tsc && ./scripts/build.copy.files.sh",
|
||||
"dev": "nodemon --exec ts-node src/ -e js,ts,gql",
|
||||
"dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/ -e js,gql",
|
||||
"lint": "eslint src --config .eslintrc.js",
|
||||
|
||||
24
backend/scripts/build.copy.files.sh
Executable file
24
backend/scripts/build.copy.files.sh
Executable file
@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
# html files
|
||||
mkdir -p build/middleware/helpers/email/templates/
|
||||
cp -r src/middleware/helpers/email/templates/*.html build/middleware/helpers/email/templates/
|
||||
|
||||
mkdir -p build/middleware/helpers/email/templates/en/
|
||||
cp -r src/middleware/helpers/email/templates/en/*.html build/middleware/helpers/email/templates/en/
|
||||
|
||||
mkdir -p build/middleware/helpers/email/templates/de/
|
||||
cp -r src/middleware/helpers/email/templates/de/*.html build/middleware/helpers/email/templates/de/
|
||||
|
||||
# gql files
|
||||
mkdir -p build/schema/types/
|
||||
cp -r src/schema/types/*.gql build/schema/types/
|
||||
|
||||
mkdir -p build/schema/types/enum/
|
||||
cp -r src/schema/types/enum/*.gql build/schema/types/enum/
|
||||
|
||||
mkdir -p build/schema/types/scalar/
|
||||
cp -r src/schema/types/scalar/*.gql build/schema/types/scalar/
|
||||
|
||||
mkdir -p build/schema/types/type/
|
||||
cp -r src/schema/types/type/*.gql build/schema/types/type/
|
||||
@ -158,7 +158,7 @@ describe('Filter Posts', () => {
|
||||
})
|
||||
|
||||
describe('order events by event start descending', () => {
|
||||
it('finds the events orderd accordingly', async () => {
|
||||
it('finds the events ordered accordingly', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({
|
||||
@ -180,7 +180,7 @@ describe('Filter Posts', () => {
|
||||
})
|
||||
|
||||
describe('order events by event start ascending', () => {
|
||||
it('finds the events orderd accordingly', async () => {
|
||||
it('finds the events ordered accordingly', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
} = await query({
|
||||
|
||||
@ -90,6 +90,9 @@ $background-color-primary-inverse: rgb(241, 253, 244);
|
||||
$background-color-secondary: rgb(0, 142, 230);
|
||||
$background-color-secondary-active: rgb(10, 161, 255);
|
||||
$background-color-secondary-inverse: rgb(240, 249, 255);
|
||||
$background-color-third: rgb(126, 82, 204);
|
||||
$background-color-third-active: rgb(160, 103, 255);
|
||||
$background-color-third-inverse: rgb(239, 230, 255);
|
||||
$background-color-success: rgb(23, 181, 63);
|
||||
$background-color-success-active: rgb(26, 203, 71);
|
||||
$background-color-success-inverse: rgb(241, 253, 244);
|
||||
@ -395,3 +398,12 @@ $color-toast-orange: $color-warning;
|
||||
$color-toast-yellow: $color-yellow;
|
||||
$color-toast-blue: $color-secondary;
|
||||
$color-toast-green: $color-success;
|
||||
|
||||
/**
|
||||
* @tokens Ribbon Color
|
||||
*/
|
||||
|
||||
$color-ribbon-event: $background-color-third;
|
||||
$color-ribbon-event-active: $background-color-third-active;
|
||||
$color-ribbon-article: $background-color-secondary;
|
||||
$color-ribbon-article-active: $background-color-secondary-active;
|
||||
@ -12,12 +12,12 @@
|
||||
<li class="item item-save-topics">
|
||||
<labeled-button filled :label="$t('actions.save')" icon="save" @click="saveCategories" />
|
||||
</li>
|
||||
<hr />
|
||||
<ds-space margin="base" />
|
||||
</template>
|
||||
|
||||
<template #filter-list>
|
||||
<div class="category-filter-list">
|
||||
<hr />
|
||||
<ds-space margin="small" />
|
||||
<base-button
|
||||
v-for="category in categories"
|
||||
:key="category.id"
|
||||
|
||||
57
webapp/components/FilterMenu/EventsByFilter.vue
Normal file
57
webapp/components/FilterMenu/EventsByFilter.vue
Normal file
@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<filter-menu-section class="order-by-filter" :title="sectionTitle" :divider="false">
|
||||
<template #filter-list>
|
||||
<li class="item">
|
||||
<labeled-button
|
||||
icon="check"
|
||||
:label="$t('filter-menu.ended.all.label')"
|
||||
:filled="!eventsEnded"
|
||||
:title="$t('filter-menu.ended.all.hint')"
|
||||
@click="toggleEventsEnded"
|
||||
data-test="all-button"
|
||||
/>
|
||||
</li>
|
||||
<li class="item">
|
||||
<labeled-button
|
||||
icon="calendar"
|
||||
:label="$t('filter-menu.ended.onlyEnded.label')"
|
||||
:filled="eventsEnded"
|
||||
:title="$t('filter-menu.ended.onlyEnded.hint')"
|
||||
@click="toggleEventsEnded"
|
||||
data-test="not-ended-button"
|
||||
/>
|
||||
</li>
|
||||
</template>
|
||||
</filter-menu-section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import FilterMenuSection from '~/components/FilterMenu/FilterMenuSection'
|
||||
import LabeledButton from '~/components/_new/generic/LabeledButton/LabeledButton'
|
||||
|
||||
export default {
|
||||
name: 'EventsByFilter',
|
||||
components: {
|
||||
FilterMenuSection,
|
||||
LabeledButton,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
postFilter: 'posts/filter',
|
||||
}),
|
||||
sectionTitle() {
|
||||
// return $t('filter-menu.eventsEnded')
|
||||
return null
|
||||
},
|
||||
eventsEnded() {
|
||||
return !!this.postFilter.eventStart_gte
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
toggleEventsEnded: 'posts/TOGGLE_EVENTS_ENDED',
|
||||
}),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -15,6 +15,7 @@ describe('FilterMenu.vue', () => {
|
||||
|
||||
const getters = {
|
||||
'posts/isActive': () => false,
|
||||
'posts/filteredPostTypes': () => [],
|
||||
'posts/orderBy': () => 'createdAt_desc',
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,10 @@
|
||||
<post-type-filter />
|
||||
<categories-filter v-if="categoriesActive" @showFilterMenu="$emit('showFilterMenu')" />
|
||||
</div>
|
||||
<div v-if="eventSetInPostTypeFilter" class="filter-menu-options">
|
||||
<h2 class="title">{{ $t('filter-menu.eventsBy') }}</h2>
|
||||
<events-by-filter />
|
||||
</div>
|
||||
<div class="filter-menu-options">
|
||||
<h2 class="title">{{ $t('filter-menu.order-by') }}</h2>
|
||||
<order-by-filter />
|
||||
@ -14,6 +18,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import EventsByFilter from './EventsByFilter'
|
||||
import PostTypeFilter from './PostTypeFilter'
|
||||
import FollowingFilter from './FollowingFilter'
|
||||
import OrderByFilter from './OrderByFilter'
|
||||
@ -21,6 +27,7 @@ import CategoriesFilter from './CategoriesFilter'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EventsByFilter,
|
||||
FollowingFilter,
|
||||
OrderByFilter,
|
||||
CategoriesFilter,
|
||||
@ -31,6 +38,14 @@ export default {
|
||||
categoriesActive: this.$env.CATEGORIES_ACTIVE,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
filteredPostTypes: 'posts/filteredPostTypes',
|
||||
}),
|
||||
eventSetInPostTypeFilter() {
|
||||
return this.filteredPostTypes.includes('Event')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -44,13 +44,12 @@ export default {
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.my-filter-button-selected {
|
||||
padding-right: 30px;
|
||||
margin-top: 4px;
|
||||
padding-right: 36px;
|
||||
}
|
||||
|
||||
.base-button.filter-remove {
|
||||
position: relative;
|
||||
margin-left: -31px;
|
||||
margin-left: -37px;
|
||||
top: -5px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
@ -11,6 +11,8 @@ describe('OrderByFilter', () => {
|
||||
'posts/TOGGLE_ORDER': jest.fn(),
|
||||
}
|
||||
const getters = {
|
||||
'posts/filteredPostTypes': () => [],
|
||||
'posts/orderedByCreationDate': () => true,
|
||||
'posts/orderBy': () => 'createdAt_desc',
|
||||
}
|
||||
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
<template>
|
||||
<filter-menu-section :divider="false" class="order-by-filter">
|
||||
<filter-menu-section class="order-by-filter" :title="sectionTitle" :divider="false">
|
||||
<template #filter-list>
|
||||
<li class="item">
|
||||
<labeled-button
|
||||
icon="sort-amount-asc"
|
||||
:label="$t('filter-menu.order.newest.label')"
|
||||
:filled="orderBy === 'createdAt_desc'"
|
||||
:title="$t('filter-menu.order.newest.hint')"
|
||||
@click="toggleOrder('createdAt_desc')"
|
||||
:label="buttonLabel('desc')"
|
||||
:filled="orderBy === orderedDesc"
|
||||
:title="buttonTitle('desc')"
|
||||
@click="toggleOrder(orderedDesc)"
|
||||
data-test="newest-button"
|
||||
/>
|
||||
</li>
|
||||
<li class="item">
|
||||
<labeled-button
|
||||
icon="sort-amount-desc"
|
||||
:label="$t('filter-menu.order.oldest.label')"
|
||||
:filled="orderBy === 'createdAt_asc'"
|
||||
:title="$t('filter-menu.order.oldest.hint')"
|
||||
@click="toggleOrder('createdAt_asc')"
|
||||
:label="buttonLabel('asc')"
|
||||
:filled="orderBy === orderedAsc"
|
||||
:title="buttonTitle('asc')"
|
||||
@click="toggleOrder(orderedAsc)"
|
||||
data-test="oldest-button"
|
||||
/>
|
||||
</li>
|
||||
@ -38,13 +38,56 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
filteredPostTypes: 'posts/filteredPostTypes',
|
||||
orderBy: 'posts/orderBy',
|
||||
}),
|
||||
orderedByCreationDate() {
|
||||
return !this.filteredPostTypes.includes('Event')
|
||||
},
|
||||
orderedAsc() {
|
||||
return this.orderedByCreationDate ? 'createdAt_asc' : 'eventStart_desc'
|
||||
},
|
||||
orderedDesc() {
|
||||
return this.orderedByCreationDate ? 'createdAt_desc' : 'eventStart_asc'
|
||||
},
|
||||
sectionTitle() {
|
||||
return this.orderedByCreationDate
|
||||
? this.$t('filter-menu.creationDate')
|
||||
: this.$t('filter-menu.startDate')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
toggleOrder: 'posts/TOGGLE_ORDER',
|
||||
}),
|
||||
buttonLabel(buttonType) {
|
||||
switch (buttonType) {
|
||||
case 'asc':
|
||||
return this.orderedByCreationDate
|
||||
? this.$t('filter-menu.order.oldest.label')
|
||||
: this.$t('filter-menu.order.last.label')
|
||||
case 'desc':
|
||||
return this.orderedByCreationDate
|
||||
? this.$t('filter-menu.order.newest.label')
|
||||
: this.$t('filter-menu.order.next.label')
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
},
|
||||
buttonTitle(buttonType) {
|
||||
switch (buttonType) {
|
||||
case 'asc':
|
||||
return this.orderedByCreationDate
|
||||
? this.$t('filter-menu.order.oldest.hint')
|
||||
: this.$t('filter-menu.order.last.hint')
|
||||
case 'desc':
|
||||
return this.orderedByCreationDate
|
||||
? this.$t('filter-menu.order.newest.hint')
|
||||
: this.$t('filter-menu.order.next.hint')
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -5,22 +5,31 @@
|
||||
class="following-filter"
|
||||
>
|
||||
<template #filter-follower>
|
||||
<li class="item all-item">
|
||||
<labeled-button
|
||||
icon="check"
|
||||
:label="$t('filter-menu.all')"
|
||||
:filled="filteredPostTypes.length === 0"
|
||||
:title="$t('filter-menu.all')"
|
||||
@click="togglePostType(null)"
|
||||
/>
|
||||
</li>
|
||||
<li class="item article-item">
|
||||
<labeled-button
|
||||
icon="book"
|
||||
:label="$t('filter-menu.article')"
|
||||
:filled="articleSet"
|
||||
:filled="filteredPostTypes.includes('Article')"
|
||||
:title="$t('filter-menu.article')"
|
||||
@click="toggleFilterPostType('Article')"
|
||||
@click="togglePostType('Article')"
|
||||
/>
|
||||
</li>
|
||||
<li class="item event-item">
|
||||
<labeled-button
|
||||
icon="calendar"
|
||||
:label="$t('filter-menu.events')"
|
||||
:filled="eventSet"
|
||||
:title="$t('filter-menu.events')"
|
||||
@click="toggleFilterPostType('Event')"
|
||||
:label="$t('filter-menu.event')"
|
||||
:filled="filteredPostTypes.includes('Event')"
|
||||
:title="$t('filter-menu.event')"
|
||||
@click="togglePostType('Event')"
|
||||
/>
|
||||
</li>
|
||||
</template>
|
||||
@ -41,18 +50,11 @@ export default {
|
||||
computed: {
|
||||
...mapGetters({
|
||||
filteredPostTypes: 'posts/filteredPostTypes',
|
||||
currentUser: 'auth/user',
|
||||
}),
|
||||
articleSet() {
|
||||
return this.filteredPostTypes.includes('Article')
|
||||
},
|
||||
eventSet() {
|
||||
return this.filteredPostTypes.includes('Event')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
toggleFilterPostType: 'posts/TOGGLE_POST_TYPE',
|
||||
togglePostType: 'posts/TOGGLE_POST_TYPE',
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import InviteButton from './InviteButton.vue'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
const stubs = {
|
||||
'v-popover': {
|
||||
template: '<span><slot /></span>',
|
||||
@ -26,7 +28,7 @@ describe('InviteButton.vue', () => {
|
||||
|
||||
describe('mount', () => {
|
||||
const Wrapper = () => {
|
||||
return mount(InviteButton, { mocks, propsData, stubs })
|
||||
return mount(InviteButton, { mocks, localVue, propsData, stubs })
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@ -25,7 +25,7 @@ export default {
|
||||
padding: $size-ribbon $size-ribbon;
|
||||
border-radius: $border-radius-small 0 0 $border-radius-small;
|
||||
color: $color-neutral-100;
|
||||
background-color: $background-color-secondary-active;
|
||||
background-color: $color-ribbon-article-active;
|
||||
font-size: $font-size-x-small;
|
||||
font-weight: $font-weight-bold;
|
||||
|
||||
@ -36,7 +36,7 @@ export default {
|
||||
bottom: -$size-ribbon;
|
||||
border-width: $border-size-large 4px $border-size-large $border-size-large;
|
||||
border-style: solid;
|
||||
border-color: $background-color-secondary transparent transparent $background-color-secondary;
|
||||
border-color: $color-ribbon-article transparent transparent $color-ribbon-article;
|
||||
}
|
||||
|
||||
&.--pinned {
|
||||
@ -48,10 +48,10 @@ export default {
|
||||
}
|
||||
}
|
||||
.eventBg {
|
||||
background-color: $color-success-active;
|
||||
background-color: $color-ribbon-event-active;
|
||||
|
||||
&::before {
|
||||
border-color: $color-success-active transparent transparent $color-success-active;
|
||||
border-color: $color-ribbon-event transparent transparent $color-ribbon-event;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -272,7 +272,9 @@
|
||||
"myFriends": "Nutzer denen ich folge",
|
||||
"myGroups": "Aus meinen Gruppen",
|
||||
"myTopics": "Meine Themen",
|
||||
"noFilter": "Beiträge filtern"
|
||||
"noFilter": "Inhalt filtern",
|
||||
"onlyArticles": "Nur Beiträge",
|
||||
"onlyEvents": "Nur Veranstaltungen"
|
||||
},
|
||||
"filterMyGroups": "Beiträge in meinen Gruppen",
|
||||
"inappropriatePicture": "Dieses Bild kann für einige Menschen unangemessen sein.",
|
||||
@ -378,31 +380,53 @@
|
||||
},
|
||||
"filter-menu": {
|
||||
"all": "Alle",
|
||||
"article": "Artikel",
|
||||
"article": "Beitrag",
|
||||
"categories": "Themen",
|
||||
"creationDate": "Erstellungszeitpunkt",
|
||||
"deleteFilter": "Filter löschen",
|
||||
"emotions": "Emotionen",
|
||||
"events": "Veranstaltungen",
|
||||
"ended": {
|
||||
"all": {
|
||||
"hint": "Zeige alle, auch beendete",
|
||||
"label": "Alle"
|
||||
},
|
||||
"onlyEnded": {
|
||||
"hint": "Zeige nur noch nicht beendete",
|
||||
"label": "Nicht beendete"
|
||||
}
|
||||
},
|
||||
"event": "Veranstaltung",
|
||||
"eventsBy": "Veranstaltungen – zeige ...",
|
||||
"eventsEnded": "Beendet",
|
||||
"filter-by": "Filtern nach ...",
|
||||
"following": "Nutzer denen ich folge",
|
||||
"languages": "Sprachen",
|
||||
"my-groups": "Meinen Gruppen",
|
||||
"order": {
|
||||
"last": {
|
||||
"hint": "Sortiere die Letzten nach vorn",
|
||||
"label": "Letzte zuerst"
|
||||
},
|
||||
"newest": {
|
||||
"hint": "Sortiere die Neuesten nach vorn",
|
||||
"label": "Neueste zuerst"
|
||||
},
|
||||
"next": {
|
||||
"hint": "Sortiere die Nächsten nach vorn",
|
||||
"label": "Nächste zuerst"
|
||||
},
|
||||
"oldest": {
|
||||
"hint": "Sortiere die Ältesten nach vorn",
|
||||
"label": "Älteste zuerst"
|
||||
}
|
||||
},
|
||||
"order-by": "Sortieren nach ...",
|
||||
"post-type": "Beitrags-Typ",
|
||||
"post-type": "Inhaltstyp",
|
||||
"save": {
|
||||
"error": "Themen konnten nicht gespeichert werden!",
|
||||
"success": "Themen gespeichert!"
|
||||
}
|
||||
},
|
||||
"startDate": "Anfangszeitpunkt"
|
||||
},
|
||||
"followButton": {
|
||||
"follow": "Folgen",
|
||||
|
||||
@ -272,7 +272,9 @@
|
||||
"myFriends": "Users I follow",
|
||||
"myGroups": "By my groups",
|
||||
"myTopics": "My topics",
|
||||
"noFilter": "Filter posts"
|
||||
"noFilter": "Filter content",
|
||||
"onlyArticles": "Only articles",
|
||||
"onlyEvents": "Only events"
|
||||
},
|
||||
"filterMyGroups": "Contributions in my groups",
|
||||
"inappropriatePicture": "This image may be inappropriate for some people.",
|
||||
@ -380,29 +382,51 @@
|
||||
"all": "All",
|
||||
"article": "Article",
|
||||
"categories": "Topics",
|
||||
"creationDate": "Creation date",
|
||||
"deleteFilter": "Delete filter",
|
||||
"emotions": "Emotions",
|
||||
"events": "Events",
|
||||
"ended": {
|
||||
"all": {
|
||||
"hint": "Show all, also ended",
|
||||
"label": "All"
|
||||
},
|
||||
"onlyEnded": {
|
||||
"hint": "Show only not ended",
|
||||
"label": "Not ended"
|
||||
}
|
||||
},
|
||||
"event": "Event",
|
||||
"eventsBy": "Events – show ...",
|
||||
"eventsEnded": "Ended",
|
||||
"filter-by": "Filter by ...",
|
||||
"following": "Users I follow",
|
||||
"languages": "Languages",
|
||||
"my-groups": "My groups",
|
||||
"order": {
|
||||
"last": {
|
||||
"hint": "Sort posts by the last first",
|
||||
"label": "Last first"
|
||||
},
|
||||
"newest": {
|
||||
"hint": "Sort posts by the newest first",
|
||||
"label": "Newest first"
|
||||
},
|
||||
"next": {
|
||||
"hint": "Sort posts by the next first",
|
||||
"label": "Next first"
|
||||
},
|
||||
"oldest": {
|
||||
"hint": "Sort posts by the oldest first",
|
||||
"label": "Oldest first"
|
||||
}
|
||||
},
|
||||
"order-by": "Order by ...",
|
||||
"post-type": "Post type",
|
||||
"post-type": "Content type",
|
||||
"save": {
|
||||
"error": "Failed saving topic settings!",
|
||||
"success": "Topics saved!"
|
||||
}
|
||||
},
|
||||
"startDate": "Start date"
|
||||
},
|
||||
"followButton": {
|
||||
"follow": "Follow",
|
||||
@ -717,7 +741,7 @@
|
||||
"unpin": "Unpin post",
|
||||
"unpinnedSuccessfully": "Post unpinned successfully!"
|
||||
},
|
||||
"name": "Post",
|
||||
"name": "Article",
|
||||
"pinned": "Announcement",
|
||||
"takeAction": {
|
||||
"name": "Take action"
|
||||
|
||||
@ -28,6 +28,10 @@ describe('PostIndex', () => {
|
||||
store = new Vuex.Store({
|
||||
getters: {
|
||||
'posts/filter': () => ({}),
|
||||
'posts/filteredPostTypes': () => [],
|
||||
'posts/articleSetInPostTypeFilter': () => false,
|
||||
'posts/eventSetInPostTypeFilter': () => false,
|
||||
'posts/eventsEnded': () => '',
|
||||
'posts/orderBy': () => 'createdAt_desc',
|
||||
'auth/user': () => {
|
||||
return { id: 'u23' }
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
<base-button
|
||||
class="my-filter-button"
|
||||
v-if="
|
||||
!postsFilter['postType_in'] &&
|
||||
!postsFilter['categories_some'] &&
|
||||
!postsFilter['author'] &&
|
||||
!postsFilter['postsInMyGroups']
|
||||
@ -38,6 +39,22 @@
|
||||
<base-icon class="my-filter-button" :name="filterButtonIcon"></base-icon>
|
||||
</base-button>
|
||||
|
||||
<header-button
|
||||
v-if="filteredPostTypes.includes('Article')"
|
||||
:title="$t('contribution.filterMasonryGrid.onlyArticles')"
|
||||
:clickButton="openFilterMenu"
|
||||
:titleRemove="$t('filter-menu.deleteFilter')"
|
||||
:clickRemove="resetPostType"
|
||||
/>
|
||||
|
||||
<header-button
|
||||
v-if="filteredPostTypes.includes('Event')"
|
||||
:title="$t('contribution.filterMasonryGrid.onlyEvents')"
|
||||
:clickButton="openFilterMenu"
|
||||
:titleRemove="$t('filter-menu.deleteFilter')"
|
||||
:clickRemove="resetPostType"
|
||||
/>
|
||||
|
||||
<header-button
|
||||
v-if="postsFilter['categories_some']"
|
||||
:title="$t('contribution.filterMasonryGrid.myTopics')"
|
||||
@ -62,7 +79,7 @@
|
||||
:clickRemove="resetByGroups"
|
||||
/>
|
||||
<div id="my-filter" v-if="showFilter">
|
||||
<div @mouseleave="showFilter = false">
|
||||
<div @mouseleave="mouseLeaveFilterMenu">
|
||||
<filter-menu-component @showFilterMenu="showFilterMenu" />
|
||||
</div>
|
||||
</div>
|
||||
@ -120,6 +137,7 @@
|
||||
|
||||
<script>
|
||||
import postListActions from '~/mixins/postListActions'
|
||||
import mobile from '~/mixins/mobile'
|
||||
import DonationInfo from '~/components/DonationInfo/DonationInfo.vue'
|
||||
import HashtagsFilter from '~/components/HashtagsFilter/HashtagsFilter.vue'
|
||||
import HcEmpty from '~/components/Empty/Empty'
|
||||
@ -134,7 +152,6 @@ import UpdateQuery from '~/components/utils/UpdateQuery'
|
||||
import FilterMenuComponent from '~/components/FilterMenu/FilterMenuComponent'
|
||||
import { SHOW_CONTENT_FILTER_MASONRY_GRID } from '~/constants/filter.js'
|
||||
import { POST_ADD_BUTTON_POSITION_TOP } from '~/constants/posts.js'
|
||||
import mobile from '~/mixins/mobile'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -154,12 +171,13 @@ export default {
|
||||
hideByScroll: false,
|
||||
revScrollpos: 0,
|
||||
showFilter: false,
|
||||
developerNoAutoClosingFilterMenu: false, // stops automatic closing of filter menu for developer purposes: default is 'false'
|
||||
showDonations: false,
|
||||
goal: 15000,
|
||||
progress: 7000,
|
||||
posts: [],
|
||||
hasMore: true,
|
||||
// Initialize your apollo data
|
||||
// initialize your apollo data
|
||||
offset: 0,
|
||||
pageSize: 12,
|
||||
hashtag,
|
||||
@ -170,14 +188,12 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
filteredPostTypes: 'posts/filteredPostTypes',
|
||||
postsFilter: 'posts/filter',
|
||||
orderBy: 'posts/orderBy',
|
||||
}),
|
||||
filterButtonIcon() {
|
||||
if (Object.keys(this.postsFilter).length === 0) {
|
||||
return this.showFilter ? 'angle-up' : 'angle-down'
|
||||
}
|
||||
return 'close'
|
||||
},
|
||||
finalFilters() {
|
||||
let filter = this.postsFilter
|
||||
@ -197,6 +213,11 @@ export default {
|
||||
},
|
||||
},
|
||||
watchQuery: ['hashtag'],
|
||||
watch: {
|
||||
postsFilter() {
|
||||
this.resetPostList()
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.categoryId) {
|
||||
this.resetCategories()
|
||||
@ -207,6 +228,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
resetPostType: 'posts/RESET_POST_TYPE',
|
||||
resetByFollowed: 'posts/TOGGLE_FILTER_BY_FOLLOWED',
|
||||
resetByGroups: 'posts/TOGGLE_FILTER_BY_MY_GROUPS',
|
||||
resetCategories: 'posts/RESET_CATEGORIES',
|
||||
@ -215,6 +237,10 @@ export default {
|
||||
openFilterMenu() {
|
||||
this.showFilter = !this.showFilter
|
||||
},
|
||||
mouseLeaveFilterMenu() {
|
||||
if (this.developerNoAutoClosingFilterMenu) return
|
||||
this.showFilter = false
|
||||
},
|
||||
showFilterMenu(e) {
|
||||
if (!e || (!e.target.closest('#my-filter') && !e.target.closest('.my-filter-button'))) {
|
||||
if (!this.showFilter) return
|
||||
|
||||
@ -18,9 +18,13 @@ describe('create.vue', () => {
|
||||
},
|
||||
}
|
||||
|
||||
const stubs = {
|
||||
ContributionForm: true,
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
const Wrapper = () => {
|
||||
return mount(create, { mocks, localVue })
|
||||
return mount(create, { mocks, localVue, stubs })
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
@ -28,7 +32,7 @@ describe('create.vue', () => {
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.findAll('.contribution-form')).toHaveLength(1)
|
||||
expect(wrapper.findComponent({ name: 'ContributionForm' }).exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -63,12 +63,6 @@ export const mutations = {
|
||||
if (isEmpty(get(filter, 'categories_some.id_in'))) delete filter.categories_some
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_POST_TYPE(state, postType) {
|
||||
const filter = clone(state.filter)
|
||||
update(filter, 'postType_in', (postTypes) => xor(postTypes, [postType]))
|
||||
if (isEmpty(get(filter, 'postType_in'))) delete filter.postType_in
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_LANGUAGE(state, languageCode) {
|
||||
const filter = clone(state.filter)
|
||||
update(filter, 'language_in', (languageCodes) => xor(languageCodes, [languageCode]))
|
||||
@ -81,6 +75,42 @@ export const mutations = {
|
||||
if (isEmpty(get(filter, 'emotions_some.emotion_in'))) delete filter.emotions_some
|
||||
state.filter = filter
|
||||
},
|
||||
RESET_POST_TYPE(state) {
|
||||
const filter = clone(state.filter)
|
||||
delete filter.eventStart_gte
|
||||
delete filter.postType_in
|
||||
state.order = 'createdAt_desc'
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_POST_TYPE(state, postType) {
|
||||
const filter = clone(state.filter)
|
||||
if (postType && !(filter.postType_in && filter.postType_in.includes(postType))) {
|
||||
filter.postType_in = [postType]
|
||||
if (postType === 'Event') {
|
||||
filter.eventStart_gte = new Date()
|
||||
state.order = 'eventStart_asc'
|
||||
} else {
|
||||
delete filter.eventStart_gte
|
||||
state.order = 'createdAt_desc'
|
||||
}
|
||||
} else {
|
||||
delete filter.eventStart_gte
|
||||
delete filter.postType_in
|
||||
state.order = 'createdAt_desc'
|
||||
}
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_EVENTS_ENDED(state) {
|
||||
const filter = clone(state.filter)
|
||||
if (filter.eventStart_gte) {
|
||||
delete filter.eventStart_gte
|
||||
} else {
|
||||
if (filter.postType_in && filter.postType_in.includes('Event')) {
|
||||
filter.eventStart_gte = new Date()
|
||||
}
|
||||
}
|
||||
state.filter = filter
|
||||
},
|
||||
TOGGLE_ORDER(state, value) {
|
||||
state.order = value
|
||||
},
|
||||
|
||||
@ -233,25 +233,49 @@ describe('mutations', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('creates post type filter if empty', () => {
|
||||
it('creates post type filter if empty, sets event start filter and event start order', () => {
|
||||
state = { filter: {} }
|
||||
expect(testMutation('Event')).toEqual({ postType_in: ['Event'] })
|
||||
expect(testMutation('Event')).toEqual({
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: expect.any(Date),
|
||||
})
|
||||
expect(getters.orderBy(state)).toEqual('eventStart_asc')
|
||||
})
|
||||
|
||||
it('adds post type not present', () => {
|
||||
state = { filter: { postType_in: ['Event'] } }
|
||||
expect(testMutation('Article')).toEqual({ postType_in: ['Event', 'Article'] })
|
||||
it('changes post type if present, resets filter event start and order', () => {
|
||||
state = {
|
||||
filter: {
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: new Date(),
|
||||
},
|
||||
order: 'eventStart_asc',
|
||||
}
|
||||
expect(testMutation('Article')).toEqual({ postType_in: ['Article'] })
|
||||
expect(getters.orderBy(state)).toEqual('createdAt_desc')
|
||||
})
|
||||
|
||||
it('removes category id if present', () => {
|
||||
state = { filter: { postType_in: ['Event', 'Article'] } }
|
||||
const result = testMutation('Event')
|
||||
expect(result).toEqual({ postType_in: ['Article'] })
|
||||
})
|
||||
|
||||
it('removes category filter if empty', () => {
|
||||
state = { filter: { postType_in: ['Event'] } }
|
||||
it('removes post type filter if same post type is present and sets order', () => {
|
||||
state = {
|
||||
filter: {
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: new Date(),
|
||||
},
|
||||
order: 'eventStart_asc',
|
||||
}
|
||||
expect(testMutation('Event')).toEqual({})
|
||||
expect(getters.orderBy(state)).toEqual('createdAt_desc')
|
||||
})
|
||||
|
||||
it('removes post type filter if called with null', () => {
|
||||
state = {
|
||||
filter: {
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: new Date(),
|
||||
},
|
||||
order: 'eventStart_asc',
|
||||
}
|
||||
expect(testMutation(null)).toEqual({})
|
||||
expect(getters.orderBy(state)).toEqual('createdAt_desc')
|
||||
})
|
||||
|
||||
it('does not get in the way of other filters', () => {
|
||||
@ -265,6 +289,67 @@ describe('mutations', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('RESET_POST_TYPE', () => {
|
||||
beforeEach(() => {
|
||||
testMutation = () => {
|
||||
mutations.RESET_POST_TYPE(state)
|
||||
return getters.filter(state)
|
||||
}
|
||||
})
|
||||
|
||||
it('resets the post type filter, event start and order', () => {
|
||||
state = {
|
||||
filter: {
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: new Date(),
|
||||
},
|
||||
order: 'eventStart_asc',
|
||||
}
|
||||
expect(testMutation()).toEqual({})
|
||||
expect(getters.orderBy(state)).toEqual('createdAt_desc')
|
||||
})
|
||||
})
|
||||
|
||||
describe('TOGGLE_EVENTS_ENDED', () => {
|
||||
beforeEach(() => {
|
||||
testMutation = (postType) => {
|
||||
mutations.TOGGLE_EVENTS_ENDED(state, postType)
|
||||
return getters.filter(state)
|
||||
}
|
||||
})
|
||||
|
||||
it('does not set events ended when post type is not Event', () => {
|
||||
state = {
|
||||
filter: {},
|
||||
}
|
||||
expect(testMutation()).toEqual({})
|
||||
})
|
||||
|
||||
it('sets events ended when post type is Event', () => {
|
||||
state = {
|
||||
filter: {
|
||||
postType_in: ['Event'],
|
||||
},
|
||||
}
|
||||
expect(testMutation()).toEqual({
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: expect.any(Date),
|
||||
})
|
||||
})
|
||||
|
||||
it('unsets events ended when set', () => {
|
||||
state = {
|
||||
filter: {
|
||||
postType_in: ['Event'],
|
||||
eventStart_gte: new Date(),
|
||||
},
|
||||
}
|
||||
expect(testMutation()).toEqual({
|
||||
postType_in: ['Event'],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('TOGGLE_FILTER_BY_FOLLOWED', () => {
|
||||
beforeEach(() => {
|
||||
testMutation = (userId) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user