commit: ed0f10e9eeb669b4fde337500649903662ab91c9
parent: e9f4244b26832009bb0648afdb8e9c48177503ae
Author: Shpuld Shpludson <shp@cock.li>
Date: Wed, 17 Apr 2019 15:43:05 +0000
Merge branch '227-bulk-delete' into 'develop'
Add "bulk mute/unmute/block/unblock" feature
See merge request pleroma/pleroma-fe!733
Diffstat:
20 files changed, 433 insertions(+), 138 deletions(-)
diff --git a/package.json b/package.json
@@ -30,7 +30,6 @@
"v-click-outside": "^2.1.1",
"vue": "^2.5.13",
"vue-chat-scroll": "^1.2.1",
- "vue-compose": "^0.7.1",
"vue-i18n": "^7.3.2",
"vue-popperjs": "^2.0.3",
"vue-router": "^3.0.1",
diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue
@@ -24,19 +24,11 @@
<script src="./basic_user_card.js"></script>
<style lang="scss">
-@import '../../_variables.scss';
-
.basic-user-card {
display: flex;
flex: 1 0;
margin: 0;
- padding-top: 0.6em;
- padding-right: 1em;
- padding-bottom: 0.6em;
- padding-left: 1em;
- border-bottom: 1px solid;
- border-bottom-color: $fallback--border;
- border-bottom-color: var(--border, $fallback--border);
+ padding: 0.6em 1em;
&-collapsed-content {
margin-left: 0.7em;
diff --git a/src/components/checkbox/checkbox.vue b/src/components/checkbox/checkbox.vue
@@ -0,0 +1,75 @@
+<template>
+ <label class="checkbox">
+ <input type="checkbox" :checked="checked" @change="$emit('change', $event.target.checked)" :indeterminate.prop="indeterminate">
+ <i class="checkbox-indicator" />
+ <span v-if="!!$slots.default"><slot></slot></span>
+ </label>
+</template>
+
+<script>
+export default {
+ model: {
+ prop: 'checked',
+ event: 'change'
+ },
+ props: ['checked', 'indeterminate']
+}
+</script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.checkbox {
+ position: relative;
+ display: inline-block;
+ padding-left: 1.2em;
+ min-height: 1.2em;
+
+ &-indicator::before {
+ position: absolute;
+ left: 0;
+ top: 0;
+ display: block;
+ content: '✔';
+ transition: color 200ms;
+ width: 1.1em;
+ height: 1.1em;
+ border-radius: $fallback--checkboxRadius;
+ border-radius: var(--checkboxRadius, $fallback--checkboxRadius);
+ box-shadow: 0px 0px 2px black inset;
+ box-shadow: var(--inputShadow);
+ background-color: $fallback--fg;
+ background-color: var(--input, $fallback--fg);
+ vertical-align: top;
+ text-align: center;
+ line-height: 1.1em;
+ font-size: 1.1em;
+ color: transparent;
+ overflow: hidden;
+ box-sizing: border-box;
+ }
+
+ input[type=checkbox] {
+ display: none;
+
+ &:checked + .checkbox-indicator::before {
+ color: $fallback--text;
+ color: var(--text, $fallback--text);
+ }
+
+ &:indeterminate + .checkbox-indicator::before {
+ content: '–';
+ color: $fallback--text;
+ color: var(--text, $fallback--text);
+ }
+
+ &:disabled + .checkbox-indicator::before {
+ opacity: .5;
+ }
+ }
+
+ & > span {
+ margin-left: .5em;
+ }
+}
+</style>
diff --git a/src/components/follow_requests/follow_requests.vue b/src/components/follow_requests/follow_requests.vue
@@ -4,7 +4,7 @@
{{$t('nav.friend_requests')}}
</div>
<div class="panel-body">
- <FollowRequestCard v-for="request in requests" :key="request.id" :user="request"/>
+ <FollowRequestCard v-for="request in requests" :key="request.id" :user="request" class="list-item"/>
</div>
</div>
</template>
diff --git a/src/components/list/list.vue b/src/components/list/list.vue
@@ -0,0 +1,42 @@
+<template>
+ <div class="list">
+ <div v-for="item in items" class="list-item" :key="getKey(item)">
+ <slot name="item" :item="item" />
+ </div>
+ <div class="list-empty-content faint" v-if="items.length === 0 && !!$slots.empty">
+ <slot name="empty" />
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ props: {
+ items: {
+ type: Array,
+ default: () => []
+ },
+ getKey: {
+ type: Function,
+ default: item => item.id
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.list {
+ &-item:not(:last-child) {
+ border-bottom: 1px solid;
+ border-bottom-color: $fallback--border;
+ border-bottom-color: var(--border, $fallback--border);
+ }
+
+ &-empty-content {
+ text-align: center;
+ padding: 10px;
+ }
+}
+</style>
diff --git a/src/components/progress_button/progress_button.vue b/src/components/progress_button/progress_button.vue
@@ -0,0 +1,35 @@
+<template>
+ <button :disabled="progress || disabled" @click="onClick">
+ <template v-if="progress">
+ <slot name="progress" />
+ </template>
+ <template v-else>
+ <slot />
+ </template>
+ </button>
+</template>
+
+<script>
+export default {
+ props: {
+ disabled: {
+ type: Boolean
+ },
+ click: { // click event handler. Must return a promise
+ type: Function,
+ default: () => Promise.resolve()
+ }
+ },
+ data () {
+ return {
+ progress: false
+ }
+ },
+ methods: {
+ onClick () {
+ this.progress = true
+ this.click().then(() => { this.progress = false })
+ }
+ }
+}
+</script>
diff --git a/src/components/selectable_list/selectable_list.js b/src/components/selectable_list/selectable_list.js
@@ -0,0 +1,66 @@
+import List from '../list/list.vue'
+import Checkbox from '../checkbox/checkbox.vue'
+
+const SelectableList = {
+ components: {
+ List,
+ Checkbox
+ },
+ props: {
+ items: {
+ type: Array,
+ default: () => []
+ },
+ getKey: {
+ type: Function,
+ default: item => item.id
+ }
+ },
+ data () {
+ return {
+ selected: []
+ }
+ },
+ computed: {
+ allKeys () {
+ return this.items.map(this.getKey)
+ },
+ filteredSelected () {
+ return this.allKeys.filter(key => this.selected.indexOf(key) !== -1)
+ },
+ allSelected () {
+ return this.filteredSelected.length === this.items.length
+ },
+ noneSelected () {
+ return this.filteredSelected.length === 0
+ },
+ someSelected () {
+ return !this.allSelected && !this.noneSelected
+ }
+ },
+ methods: {
+ isSelected (item) {
+ return this.filteredSelected.indexOf(this.getKey(item)) !== -1
+ },
+ toggle (checked, item) {
+ const key = this.getKey(item)
+ const oldChecked = this.isSelected(key)
+ if (checked !== oldChecked) {
+ if (checked) {
+ this.selected.push(key)
+ } else {
+ this.selected.splice(this.selected.indexOf(key), 1)
+ }
+ }
+ },
+ toggleAll (value) {
+ if (value) {
+ this.selected = this.allKeys.slice(0)
+ } else {
+ this.selected = []
+ }
+ }
+ }
+}
+
+export default SelectableList
diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue
@@ -0,0 +1,59 @@
+<template>
+ <div class="selectable-list">
+ <div class="selectable-list-header" v-if="items.length > 0">
+ <div class="selectable-list-checkbox-wrapper">
+ <Checkbox :checked="allSelected" @change="toggleAll" :indeterminate="someSelected">{{ $t('selectable_list.select_all') }}</Checkbox>
+ </div>
+ <div class="selectable-list-header-actions">
+ <slot name="header" :selected="filteredSelected" />
+ </div>
+ </div>
+ <List :items="items" :getKey="getKey">
+ <template slot="item" slot-scope="{item}">
+ <div class="selectable-list-item-inner" :class="{ 'selectable-list-item-selected-inner': isSelected(item) }">
+ <div class="selectable-list-checkbox-wrapper">
+ <Checkbox :checked="isSelected(item)" @change="checked => toggle(checked, item)" />
+ </div>
+ <slot name="item" :item="item" />
+ </div>
+ </template>
+ <template slot="empty"><slot name="empty" /></template>
+ </List>
+ </div>
+</template>
+
+<script src="./selectable_list.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.selectable-list {
+ &-item-inner {
+ display: flex;
+ align-items: center;
+ }
+
+ &-item-selected-inner {
+ background-color: $fallback--lightBg;
+ background-color: var(--lightBg, $fallback--lightBg);
+ }
+
+ &-header {
+ display: flex;
+ align-items: center;
+ padding: 0.6em 0;
+ border-bottom: 2px solid;
+ border-bottom-color: $fallback--border;
+ border-bottom-color: var(--border, $fallback--border);
+
+ &-actions {
+ flex: 1;
+ }
+ }
+
+ &-checkbox-wrapper {
+ padding: 0 10px;
+ flex: none;
+ }
+}
+</style>
diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js
@@ -1,33 +1,26 @@
-import { compose } from 'vue-compose'
import get from 'lodash/get'
import UserCard from '../user_card/user_card.vue'
import FollowCard from '../follow_card/follow_card.vue'
import Timeline from '../timeline/timeline.vue'
import ModerationTools from '../moderation_tools/moderation_tools.vue'
+import List from '../list/list.vue'
import withLoadMore from '../../hocs/with_load_more/with_load_more'
-import withList from '../../hocs/with_list/with_list'
-const FollowerList = compose(
- withLoadMore({
- fetch: (props, $store) => $store.dispatch('fetchFollowers', props.userId),
- select: (props, $store) => get($store.getters.findUser(props.userId), 'followerIds', []).map(id => $store.getters.findUser(id)),
- destory: (props, $store) => $store.dispatch('clearFollowers', props.userId),
- childPropName: 'entries',
- additionalPropNames: ['userId']
- }),
- withList({ getEntryProps: user => ({ user }) })
-)(FollowCard)
+const FollowerList = withLoadMore({
+ fetch: (props, $store) => $store.dispatch('fetchFollowers', props.userId),
+ select: (props, $store) => get($store.getters.findUser(props.userId), 'followerIds', []).map(id => $store.getters.findUser(id)),
+ destroy: (props, $store) => $store.dispatch('clearFollowers', props.userId),
+ childPropName: 'items',
+ additionalPropNames: ['userId']
+})(List)
-const FriendList = compose(
- withLoadMore({
- fetch: (props, $store) => $store.dispatch('fetchFriends', props.userId),
- select: (props, $store) => get($store.getters.findUser(props.userId), 'friendIds', []).map(id => $store.getters.findUser(id)),
- destory: (props, $store) => $store.dispatch('clearFriends', props.userId),
- childPropName: 'entries',
- additionalPropNames: ['userId']
- }),
- withList({ getEntryProps: user => ({ user }) })
-)(FollowCard)
+const FriendList = withLoadMore({
+ fetch: (props, $store) => $store.dispatch('fetchFriends', props.userId),
+ select: (props, $store) => get($store.getters.findUser(props.userId), 'friendIds', []).map(id => $store.getters.findUser(id)),
+ destroy: (props, $store) => $store.dispatch('clearFriends', props.userId),
+ childPropName: 'items',
+ additionalPropNames: ['userId']
+})(List)
const UserProfile = {
data () {
@@ -134,7 +127,8 @@ const UserProfile = {
Timeline,
FollowerList,
FriendList,
- ModerationTools
+ ModerationTools,
+ FollowCard
}
}
diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue
@@ -14,10 +14,18 @@
:user-id="userId"
/>
<div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count">
- <FriendList :userId="userId" />
+ <FriendList :userId="userId">
+ <template slot="item" slot-scope="{item}">
+ <FollowCard :user="item" />
+ </template>
+ </FriendList>
</div>
<div :label="$t('user_card.followers')" v-if="followersTabVisible" :disabled="!user.followers_count">
- <FollowerList :userId="userId" :entryProps="{noFollowsYou: isUs}" />
+ <FollowerList :userId="userId">
+ <template slot="item" slot-scope="{item}">
+ <FollowCard :user="item" :noFollowsYou="isUs" />
+ </template>
+ </FollowerList>
</div>
<Timeline
:label="$t('user_card.media')"
diff --git a/src/components/user_search/user_search.vue b/src/components/user_search/user_search.vue
@@ -13,7 +13,7 @@
<i class="icon-spin3 animate-spin"/>
</div>
<div v-else class="panel-body">
- <FollowCard v-for="user in users" :key="user.id" :user="user"/>
+ <FollowCard v-for="user in users" :key="user.id" :user="user" class="list-item"/>
</div>
</div>
</template>
diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
@@ -1,4 +1,3 @@
-import { compose } from 'vue-compose'
import unescape from 'lodash/unescape'
import get from 'lodash/get'
import map from 'lodash/map'
@@ -10,29 +9,24 @@ import ScopeSelector from '../scope_selector/scope_selector.vue'
import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
import BlockCard from '../block_card/block_card.vue'
import MuteCard from '../mute_card/mute_card.vue'
+import SelectableList from '../selectable_list/selectable_list.vue'
+import ProgressButton from '../progress_button/progress_button.vue'
import EmojiInput from '../emoji-input/emoji-input.vue'
import Autosuggest from '../autosuggest/autosuggest.vue'
import withSubscription from '../../hocs/with_subscription/with_subscription'
-import withList from '../../hocs/with_list/with_list'
import userSearchApi from '../../services/new_api/user_search.js'
-const BlockList = compose(
- withSubscription({
- fetch: (props, $store) => $store.dispatch('fetchBlocks'),
- select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
- childPropName: 'entries'
- }),
- withList({ getEntryProps: userId => ({ userId }) })
-)(BlockCard)
+const BlockList = withSubscription({
+ fetch: (props, $store) => $store.dispatch('fetchBlocks'),
+ select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []),
+ childPropName: 'items'
+})(SelectableList)
-const MuteList = compose(
- withSubscription({
- fetch: (props, $store) => $store.dispatch('fetchMutes'),
- select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
- childPropName: 'entries'
- }),
- withList({ getEntryProps: userId => ({ userId }) })
-)(MuteCard)
+const MuteList = withSubscription({
+ fetch: (props, $store) => $store.dispatch('fetchMutes'),
+ select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []),
+ childPropName: 'items'
+})(SelectableList)
const UserSettings = {
data () {
@@ -80,7 +74,8 @@ const UserSettings = {
EmojiInput,
Autosuggest,
BlockCard,
- MuteCard
+ MuteCard,
+ ProgressButton
},
computed: {
user () {
@@ -360,6 +355,21 @@ const UserSettings = {
this.$store.dispatch('addNewUsers', users)
return map(users, 'id')
})
+ },
+ blockUsers (ids) {
+ return this.$store.dispatch('blockUsers', ids)
+ },
+ unblockUsers (ids) {
+ return this.$store.dispatch('unblockUsers', ids)
+ },
+ muteUsers (ids) {
+ return this.$store.dispatch('muteUsers', ids)
+ },
+ unmuteUsers (ids) {
+ return this.$store.dispatch('unmuteUsers', ids)
+ },
+ identity (value) {
+ return value
}
}
}
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
@@ -200,9 +200,22 @@
<BlockCard slot-scope="row" :userId="row.item"/>
</Autosuggest>
</div>
- <block-list :refresh="true">
+ <BlockList :refresh="true" :getKey="identity">
+ <template slot="header" slot-scope="{selected}">
+ <div class="profile-edit-bulk-actions">
+ <ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => blockUsers(selected)">
+ {{ $t('user_card.block') }}
+ <template slot="progress">{{ $t('user_card.block_progress') }}</template>
+ </ProgressButton>
+ <ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => unblockUsers(selected)">
+ {{ $t('user_card.unblock') }}
+ <template slot="progress">{{ $t('user_card.unblock_progress') }}</template>
+ </ProgressButton>
+ </div>
+ </template>
+ <template slot="item" slot-scope="{item}"><BlockCard :userId="item" /></template>
<template slot="empty">{{$t('settings.no_blocks')}}</template>
- </block-list>
+ </BlockList>
</div>
<div :label="$t('settings.mutes_tab')">
@@ -211,9 +224,22 @@
<MuteCard slot-scope="row" :userId="row.item"/>
</Autosuggest>
</div>
- <mute-list :refresh="true">
+ <MuteList :refresh="true" :getKey="identity">
+ <template slot="header" slot-scope="{selected}">
+ <div class="profile-edit-bulk-actions">
+ <ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => muteUsers(selected)">
+ {{ $t('user_card.mute') }}
+ <template slot="progress">{{ $t('user_card.mute_progress') }}</template>
+ </ProgressButton>
+ <ProgressButton class="btn btn-default" v-if="selected.length > 0" :click="() => unmuteUsers(selected)">
+ {{ $t('user_card.unmute') }}
+ <template slot="progress">{{ $t('user_card.unmute_progress') }}</template>
+ </ProgressButton>
+ </div>
+ </template>
+ <template slot="item" slot-scope="{item}"><MuteCard :userId="item" /></template>
<template slot="empty">{{$t('settings.no_mutes')}}</template>
- </mute-list>
+ </MuteList>
</div>
</tab-switcher>
</div>
@@ -276,5 +302,15 @@
&-usersearch-wrapper {
padding: 1em;
}
+
+ &-bulk-actions {
+ text-align: right;
+ padding: 0 1em;
+ min-height: 28px;
+
+ button {
+ width: 10em;
+ }
+ }
}
</style>
diff --git a/src/components/who_to_follow/who_to_follow.vue b/src/components/who_to_follow/who_to_follow.vue
@@ -4,7 +4,7 @@
{{$t('who_to_follow.who_to_follow')}}
</div>
<div class="panel-body">
- <FollowCard v-for="user in users" :key="user.id" :user="user"/>
+ <FollowCard v-for="user in users" :key="user.id" :user="user" class="list-item"/>
</div>
</div>
</template>
diff --git a/src/hocs/with_list/with_list.js b/src/hocs/with_list/with_list.js
@@ -1,40 +0,0 @@
-import Vue from 'vue'
-import map from 'lodash/map'
-import isEmpty from 'lodash/isEmpty'
-import './with_list.scss'
-
-const defaultEntryPropsGetter = entry => ({ entry })
-const defaultKeyGetter = entry => entry.id
-
-const withList = ({
- getEntryProps = defaultEntryPropsGetter, // function to accept entry and index values and return props to be passed into the item component
- getKey = defaultKeyGetter // funciton to accept entry and index values and return key prop value
-}) => (ItemComponent) => (
- Vue.component('withList', {
- props: [
- 'entries', // array of entry
- 'entryProps', // additional props to be passed into each entry
- 'entryListeners' // additional event listeners to be passed into each entry
- ],
- render (createElement) {
- return (
- <div class="with-list">
- {map(this.entries, (entry, index) => {
- const props = {
- key: getKey(entry, index),
- props: {
- ...this.$props.entryProps,
- ...getEntryProps(entry, index)
- },
- on: this.$props.entryListeners
- }
- return <ItemComponent {...props} />
- })}
- {isEmpty(this.entries) && this.$slots.empty && <div class="with-list-empty-content faint">{this.$slots.empty}</div>}
- </div>
- )
- }
- })
-)
-
-export default withList
diff --git a/src/hocs/with_list/with_list.scss b/src/hocs/with_list/with_list.scss
@@ -1,6 +0,0 @@
-.with-list {
- &-empty-content {
- text-align: center;
- padding: 10px;
- }
-}-
\ No newline at end of file
diff --git a/src/hocs/with_load_more/with_load_more.scss b/src/hocs/with_load_more/with_load_more.scss
@@ -1,10 +1,16 @@
+
+@import '../../_variables.scss';
+
.with-load-more {
&-footer {
padding: 10px;
text-align: center;
+ border-top: 1px solid;
+ border-top-color: $fallback--border;
+ border-top-color: var(--border, $fallback--border);
.error {
font-size: 14px;
}
}
-}-
\ No newline at end of file
+}
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -112,6 +112,9 @@
"password_confirmation_match": "should be the same as password"
}
},
+ "selectable_list": {
+ "select_all": "Select all"
+ },
"settings": {
"app_name": "App name",
"attachmentRadius": "Attachments",
diff --git a/src/modules/users.js b/src/modules/users.js
@@ -32,6 +32,35 @@ const getNotificationPermission = () => {
return Promise.resolve(Notification.permission)
}
+const blockUser = (store, id) => {
+ return store.rootState.api.backendInteractor.blockUser(id)
+ .then((relationship) => {
+ store.commit('updateUserRelationship', [relationship])
+ store.commit('addBlockId', id)
+ store.commit('removeStatus', { timeline: 'friends', userId: id })
+ store.commit('removeStatus', { timeline: 'public', userId: id })
+ store.commit('removeStatus', { timeline: 'publicAndExternal', userId: id })
+ })
+}
+
+const unblockUser = (store, id) => {
+ return store.rootState.api.backendInteractor.unblockUser(id)
+ .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+}
+
+const muteUser = (store, id) => {
+ return store.rootState.api.backendInteractor.muteUser(id)
+ .then((relationship) => {
+ store.commit('updateUserRelationship', [relationship])
+ store.commit('addMuteId', id)
+ })
+}
+
+const unmuteUser = (store, id) => {
+ return store.rootState.api.backendInteractor.unmuteUser(id)
+ .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+}
+
export const mutations = {
setMuted (state, { user: { id }, muted }) {
const user = state.usersObject[id]
@@ -206,19 +235,17 @@ const users = {
return blocks
})
},
- blockUser (store, userId) {
- return store.rootState.api.backendInteractor.blockUser(userId)
- .then((relationship) => {
- store.commit('updateUserRelationship', [relationship])
- store.commit('addBlockId', userId)
- store.commit('removeStatus', { timeline: 'friends', userId })
- store.commit('removeStatus', { timeline: 'public', userId })
- store.commit('removeStatus', { timeline: 'publicAndExternal', userId })
- })
+ blockUser (store, id) {
+ return blockUser(store, id)
},
unblockUser (store, id) {
- return store.rootState.api.backendInteractor.unblockUser(id)
- .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+ return unblockUser(store, id)
+ },
+ blockUsers (store, ids = []) {
+ return Promise.all(ids.map(id => blockUser(store, id)))
+ },
+ unblockUsers (store, ids = []) {
+ return Promise.all(ids.map(id => unblockUser(store, id)))
},
fetchMutes (store) {
return store.rootState.api.backendInteractor.fetchMutes()
@@ -229,15 +256,16 @@ const users = {
})
},
muteUser (store, id) {
- return store.rootState.api.backendInteractor.muteUser(id)
- .then((relationship) => {
- store.commit('updateUserRelationship', [relationship])
- store.commit('addMuteId', id)
- })
+ return muteUser(store, id)
},
unmuteUser (store, id) {
- return store.rootState.api.backendInteractor.unmuteUser(id)
- .then((relationship) => store.commit('updateUserRelationship', [relationship]))
+ return unmuteUser(store, id)
+ },
+ muteUsers (store, ids = []) {
+ return Promise.all(ids.map(id => muteUser(store, id)))
+ },
+ unmuteUsers (store, ids = []) {
+ return Promise.all(ids.map(id => unmuteUser(store, id)))
},
fetchFriends ({ rootState, commit }, id) {
const user = rootState.users.usersObject[id]
diff --git a/yarn.lock b/yarn.lock
@@ -6430,16 +6430,6 @@ vue-chat-scroll@^1.2.1:
version "1.3.5"
resolved "https://registry.yarnpkg.com/vue-chat-scroll/-/vue-chat-scroll-1.3.5.tgz#a5ee5bae5058f614818a96eac5ee3be4394a2f68"
-vue-compose@^0.7.1:
- version "0.7.1"
- resolved "https://registry.yarnpkg.com/vue-compose/-/vue-compose-0.7.1.tgz#1c11c4cd5e2c8f2743b03fce8ab43d78aabc20b3"
- dependencies:
- vue-hoc "0.x.x"
-
-vue-hoc@0.x.x:
- version "0.4.7"
- resolved "https://registry.yarnpkg.com/vue-hoc/-/vue-hoc-0.4.7.tgz#4d3322ba89b8b0e42b19045ef536c21d948a4fac"
-
vue-hot-reload-api@^2.0.11:
version "2.3.1"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz#b2d3d95402a811602380783ea4f566eb875569a2"