Skip to content

Commit

Permalink
Implement blacklist on the frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
roschaefer committed Sep 26, 2018
1 parent daf9443 commit 2414f0a
Show file tree
Hide file tree
Showing 23 changed files with 1,369 additions and 946 deletions.
11 changes: 11 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"env": {
"test": {
"plugins": ["transform-object-rest-spread"],
"presets": [
["env", { "targets": { "node": "current" }}]
]
}
}
}

1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = {
sourceType: 'module'
},
env: {
jest: true,
browser: true,
node: true
},
Expand Down
76 changes: 76 additions & 0 deletions components/Global/Elements/BlockButton/BlockButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<template>
<div class="columns is-mobile field has-text-centered">
<div class="column control has-text-centered">
<hc-button color="button"
:disabled="isPending"
:isLoading="isPending"
@click="click">
<template v-if="isBlacklisted()">
<hc-icon icon="ban" :class="['icon-left', 'is-danger']" /> {{ $t('component.blacklist.buttonLabelUnblock') }}
</template>
<template v-else>
<hc-icon icon="ban" class="icon-left" /> {{ $t('component.blacklist.buttonLabelBlock') }}
</template>
</hc-button>
</div>
</div>
</template>
<script>
import Icon from '~/components/Global/Elements/Icon/Icon.vue'
import Button from '~/components/Global/Elements/Button/Button.vue'
import { mapGetters } from 'vuex'
export default {
name: 'hc-block-button',
components: {
'hc-button': Button,
'hc-icon': Icon
},
props: {
foreignEntity: {
type: Object,
required: true
},
confirmation: {
type: Function
}
},
computed: {
...mapGetters({
isPending: 'feathers-vuex-usersettings/isPending',
currentUserSettings: 'feathers-vuex-usersettings/current'
})
},
methods: {
isBlacklisted () {
let { blacklist } = this.currentUserSettings || {}
return blacklist && blacklist.includes(this.foreignEntity._id)
},
async click(){
if (this.confirmation && !this.isBlacklisted()) {
return await this.confirmation(this.toggleBlacklist)
} else return await this.toggleBlacklist()
},
async toggleBlacklist() {
let message
try {
await this.$store.dispatch('feathers-vuex-usersettings/toggleBlacklist', this.foreignEntity)
const translationKey = `component.blacklist.${this.isBlacklisted() ? 'blockSuccess' : 'unblockSuccess'}`
message = this.$t(translationKey, {
name: this.foreignEntity.name || this.$t('component.contribution.creatorUnknown')
})
} catch (error) {
message = this.$t('component.error.general')
throw (error)
} finally {
this.$snackbar.open({ message })
}
}
}
}
</script>

<style lang="scss" scoped>
@import "assets/styles/utilities";
</style>
2 changes: 1 addition & 1 deletion components/Global/Elements/Follow/FollowButtons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<div v-if="showButtons" class="columns is-mobile field has-text-centered">
<div class="column control has-text-centered">
<hc-button color="button is-fullwidth"
:class="{'is-primary': !follow.isLoading && !follow.isPending && !follow.isFollowing}"
:class="{'is-primary': !follow.isPending && !follow.isFollowing}"
@click="toggleFollow"
:disabled="follow.isPending"
:isLoading="follow.isPending">
Expand Down
14 changes: 13 additions & 1 deletion locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@
"messageFollowSuccess": "Du folgst {name} nun",
"messageUnFollowSuccess": "Du folgst {name} nicht mehr"
},
"blacklist": {
"buttonLabelBlock": "Blockieren",
"buttonLabelUnblock": "Blockiert",
"confirmUnfollowTitle": "Nicht mehr Folgen",
"confirmUnfollowMessage": "Möchtest Du {name} nicht mehr folgen und dessen Inhalte nie mehr sehen?",
"blockSuccess": "Du wirst keine Inhalte von {name} mehr sehen",
"unblockSuccess": "Du wirst wieder Inhalte von {name} sehen"
},
"admin": {
"activate": "Aktivieren",
"addCategory": "Kategorie hinzufügen",
Expand Down Expand Up @@ -165,6 +173,8 @@
"actionReport": "Beitrag melden",
"actionDisable": "Beitrag deaktivieren",
"actionEnable": "Beitrag aktivieren",
"actionBlockAuthor": "Autor blockieren",
"actionUnblockAuthor": "Autor freigeben",
"bestList": "Bestenliste",
"canDos": "Can Do",
"canDoAdd": "Can Do starten",
Expand Down Expand Up @@ -621,7 +631,9 @@
"organizationStreet": "Straße",
"organizationZipCode": "PLZ",
"organizationCity": "Stadt",
"organizationCountry": "Land"
"organizationCountry": "Land",
"blacklist": "Sperrliste",
"blacklistSubtitle": "Nutzerprofile deren Inhalte Du nicht mehr siehst"
}
},
"ressource": {
Expand Down
17 changes: 15 additions & 2 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"copy403": "Sorry, access to this resource on the server is denied. <br />Either check the URL, <a href=\"/auth/login\">login</a> or <a href=\"/\">go home</a>.",
"copy404": "Sorry, the page you're looking for cannot be found. <br />Either check the URL, <a href=\"/\">go home</a>, or feel free to <a href=\"mailto:[email protected]\">report this issue.</a>",
"copy500": "An error ocurred and your request couldn’t be completed. <br />Either check the URL, <a href=\"/\">go home</a>, or feel free to <a href=\"mailto:[email protected]\">report this issue.</a>",
"copy503": "We are currently working on it, <br />so take a coffee brake and come back a bit later."
"copy503": "We are currently working on it, <br />so take a coffee brake and come back a bit later.",
"general": "Oops, something went terribly wrong"
},
"badges": {
"user_role_moderator": "Moderator",
Expand Down Expand Up @@ -60,6 +61,14 @@
"messageFollowSuccess": "You now follow {name}",
"messageUnFollowSuccess": "You not longer follow {name}"
},
"blacklist": {
"buttonLabelBlock": "Block",
"buttonLabelUnblock": "Blocked",
"confirmUnfollowTitle": "Unfollow",
"confirmUnfollowMessage": "Do you want to unfollow and block any content by {name}?",
"blockSuccess": "You will no longer see any content by {name}",
"unblockSuccess": "You will see content by {name} again"
},
"admin": {
"activate": "Activate",
"addCategory": "add category",
Expand Down Expand Up @@ -166,6 +175,8 @@
"actionReport": "report post",
"actionDisable": "disable post",
"actionEnable": "enable post",
"actionBlockAuthor": "block author",
"actionUnblockAuthor": "unblock author",
"bestList": "Bestlist",
"canDos": "Can Do’s",
"canDoAdd": "Start Can Do",
Expand Down Expand Up @@ -623,7 +634,9 @@
"organizationStreet": "Street",
"organizationZipCode": "Zip Code",
"organizationCity": "City",
"organizationCountry": "Country"
"organizationCountry": "Country",
"blacklist": "Blacklist",
"blacklistSubtitle": "Users whose content you no longer see"
}
},
"ressource": {
Expand Down
31 changes: 22 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"eslint": "eslint --ext .js,.vue .",
"styleguide": "vue-styleguidist server",
"styleguide:build": "vue-styleguidist build",
"test": "ava",
"test": "jest",
"cypress:open": "cypress open",
"cypress:run": "cypress run",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov"
Expand Down Expand Up @@ -117,10 +117,10 @@
},
"devDependencies": {
"@nuxtjs/webpackmonitor": "~0.1.0",
"@vue/test-utils": "^1.0.0-beta.20",
"ava": "~0.25.0",
"@vue/server-test-utils": "^1.0.0-beta.25",
"@vue/test-utils": "^1.0.0-beta.25",
"babel-jest": "^23.6.0",
"backpack-core": "~0.7.0",
"browser-env": "~3.2.4",
"codecov": "~3.0.4",
"eslint": "~4.19.1",
"eslint-config-standard": "~11.0.0-beta.0",
Expand All @@ -132,21 +132,34 @@
"eslint-plugin-standard": "~3.1.0",
"eslint-plugin-vue": "^4.5.0",
"istanbul": "~0.4.5",
"jsdom": "~11.10.0",
"jest": "^23.6.0",
"jsdom": "^12.0.0",
"jsdom-global": "^3.0.2",
"less": "~2.7.3",
"less-loader": "^4.1.0",
"node-sass": "~4.9.0",
"require-extension-hooks": "~0.3.2",
"require-extension-hooks-babel": "~0.1.1",
"require-extension-hooks-vue": "~1.0.0",
"sass-loader": "~6.0.7",
"sinon": "^6.3.4",
"source-map-support": "~0.5.6",
"vue-docgen-api": "^2.3.11",
"vue-jest": "^2.6.0",
"vue-style-loader": "~4.1.0"
},
"ava": {
"require": [
"./test/helpers/setup.js"
]
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"moduleNameMapper": {
"^~/(.*)$": "<rootDir>/$1"
},
"transform": {
".*\\.(vue)$": "vue-jest",
"^.+\\.js$": "<rootDir>/node_modules/babel-jest"
}
}
}
3 changes: 3 additions & 0 deletions pages/auth/settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<li>
<nuxt-link :to="{ name: 'auth-settings-security' }">{{ $t('auth.settings.security', 'Security') }}</nuxt-link>
</li>
<li>
<nuxt-link :to="{ name: 'auth-settings-blacklist' }">{{ $t('auth.settings.blacklist', 'Blacklist') }}</nuxt-link>
</li>
<li v-if="showInvites">
<nuxt-link :to="{ name: 'auth-settings-invites' }">{{ $t('auth.settings.invites', 'Invites') }}</nuxt-link>
</li>
Expand Down
38 changes: 38 additions & 0 deletions pages/auth/settings/blacklist.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<div class="info-text">
<h2 class="title is-3">
{{ $t('auth.settings.blacklist') }}
</h2>
<p class="subtitle is-6">{{ $t('auth.settings.blacklistSubtitle') }}</p>
<author
v-for="(user, index) in blacklistedUsers"
:key="user._id"
:user="user"
/>
</div>
</template>

<script>
import Author from '~/components/Author/Author.vue'
export default {
components: {
Author
},
data() {
return {
blacklistedUsers: [],
}
},
async asyncData ({store}) {
const { blacklist } = store.getters['feathers-vuex-usersettings/current'];
if (!blacklist) return {}
const res = await store.dispatch('feathers-vuex-users/find', { query: {_id: { $in: blacklist } } } );
return {
blacklistedUsers: res.data
}
}
};
</script>

<style lang="scss" scoped>
</style>
18 changes: 18 additions & 0 deletions pages/profile/_slug.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
<hc-follow-buttons v-if="user"
:showButtons="!isOwner"
:entity="user" />

<hc-block-button v-if="user && !isOwner" :foreignEntity="user" :confirmation="confirmUnfollow"/>
<div v-if="false" class="hc-shortcuts level under-construction">
<!-- TODO: replace the cdn images with local hc icons -->
<div class="level-item has-text-centered">
Expand Down Expand Up @@ -140,6 +142,7 @@
import {mapGetters} from 'vuex'
import FollowerItem from '~/components/Profile/FollowerItem/FollowerItem.vue'
import FollowButtons from '~/components/Global/Elements/Follow/FollowButtons.vue'
import BlockButton from '~/components/Global/Elements/BlockButton/BlockButton'
import Map from '~/components/Map/Map.vue'
import Timeline from '~/components/layout/Timeline'
import Badges from '~/components/Profile/Badges/Badges'
Expand All @@ -150,6 +153,7 @@
components: {
'hc-follower-item': FollowerItem,
'hc-follow-buttons': FollowButtons,
'hc-block-button': BlockButton,
'hc-profile-badges': Badges,
'hc-map': Map,
'hc-timeline': Timeline
Expand Down Expand Up @@ -261,6 +265,20 @@
}
},
methods: {
confirmUnfollow(next){
const message = this.$t('component.blacklist.confirmUnfollowMessage', {
name: this.user.name || this.$t('component.contribution.creatorUnknown')
})
this.$dialog.confirm({
title: this.$t('component.blacklist.confirmUnfollowTitle'),
message,
confirmText: this.$t('button.yes'),
cancelText: this.$t('button.cancel'),
type: 'is-danger',
hasIcon: true,
onConfirm: () => { next() }
})
},
async onCoverUploadCompleted (value) {
this.form.coverImg = value
const user = await this.$store.dispatch('auth/patch', {
Expand Down
6 changes: 0 additions & 6 deletions plugins/api.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import feathersVuex from 'feathers-vuex'
import Vue from 'vue'
import Vuex from 'vuex'
import createApiClient from '../helpers/createApiClient'

export default ({app, store, redirect, router, req, res}) => {
const api = createApiClient({app, req, res})
const { FeathersVuex } = feathersVuex(api, { idField: '_id' })

Vue.use(FeathersVuex)
Vue.use(Vuex)

api.hooks({
before: {
Expand Down
7 changes: 7 additions & 0 deletions plugins/init-feathers-vuex.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import Vue from 'vue'
import Vuex from 'vuex'
import createApiClient from '../helpers/createApiClient'
import feathersVuex from 'feathers-vuex'

const requireModule = require.context(
// The relative path holding the service modules
Expand All @@ -11,6 +14,10 @@ const requireModule = require.context(

export default async ({app, store, req, res}) => {
const feathersClient = createApiClient({app, req, res})
const { FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' })

Vue.use(FeathersVuex)
Vue.use(Vuex)

const servicePlugins = requireModule.keys().map(modulePath => requireModule(modulePath).default(feathersClient))
servicePlugins.forEach((servicePlugin) => {
Expand Down
2 changes: 2 additions & 0 deletions store/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export const actions = {
}
commit('SET_USER', user)
}
dispatch('feathers-vuex-usersettings/loadCurrent', user, { root: true })
return user
},
async checkAuth ({state, getters, commit, dispatch}) {
Expand Down Expand Up @@ -128,6 +129,7 @@ export const actions = {
commit('SET_USER', null)
commit('SET_TOKEN', null)
const user = await this.app.$api.auth({strategy: 'local', email, password})
dispatch('feathers-vuex-usersettings/loadCurrent', user, { root: true })

commit('SET_USER', user)

Expand Down
2 changes: 2 additions & 0 deletions store/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export const strict = false

export const actions = {
async nuxtServerInit ({dispatch}) {
dispatch('categories/init')
Expand Down
Loading

0 comments on commit 2414f0a

Please sign in to comment.